JavaWeb 后端 <十二> 之 过滤器 filter 乱码、不缓存、脏话、标记、自动登录、全站压缩过滤器

一、过滤器是什么?有什么?

1、过滤器属于Servlet规范,从2.3版本就开始有了。

2、过滤器就是对访问的内容进行筛选(拦截)。利用过滤器对请求和响应进行过滤

二、编写步骤和执行过程

1、编码步骤:

a、编写一个类:实现javax.servlet.Filter接口

public class FilterDemo1 implements Filter {
     
    public FilterDemo1(){
        System.out.println("调用了默认的构造方法");
    }
     
    //用户每次访问被过滤的资源,都会由服务器调用该方法实现过滤
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("FilterDemo1执行过滤前");
        //对请求进行拦截,代码写在这
        chain.doFilter(request, response);//放行
        //对响应进行拦截,代码写在这
        System.out.println("FilterDemo1执行过滤后");
    }
 
    public void destroy() {
        System.out.println("调用了销毁方法");
    }
 
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("调用初始化方法");
    }
 
}

 b、配置web.xml,指定需要过滤的资源。(和Servlet的配置相当类似)

2、过滤器的执行过程(生命周期)

生命周期:

诞生:过滤器的实例是在应用被加载时就完成的实例化,并初始化的。

存活:和应用的生命周期一致的。在内存中是单例的。针对拦截范围内的资源访问,每次访问都会调用void doFIlter(request,response.chain)进行拦截。

死亡:应用被卸载。

 

三、串联过滤器

一个过滤器接着另外一个过滤器。执行的顺序  按照web.xml的先后顺序

随意 访问  会先直接FilterDemo2 的 再执行 FilterDemo3的

会输出 :

FilterDemo2前

FilterDemo3前

执行内容

FilterDemo3后

FilterDemo2后

四、案例:

1、解决请求参数(POST)和响应输出的乱码过滤器

//解决post方式请求参数和响应编码问题的过滤器
public class SetCharacterEncodingFilter implements Filter {
    private FilterConfig filterConfig;
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }
 
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
         
        String encoding = filterConfig.getInitParameter("encoding");//用户可能忘记了配置该参数
        if(encoding==null){
            encoding = "UTF-8";//默认编码
        }
         
        request.setCharacterEncoding(encoding);//只能解决POST请求参数的中文问题
        response.setCharacterEncoding(encoding);//输出流编码
        response.setContentType("text/html;charset="+encoding);//输出流编码,通知了客户端应该使用的编码
        chain.doFilter(request, response);
    }
 
    public void destroy() {
 
    }
 
}

将 编码类型写在 Filter参数中

 

 

2、动态资源不要缓存的过滤器

Servlet/JSP:动态资源不要缓存。

 

这里 将 Servletrequest 和 ServletResponse 转换为 HttpServlet 的方法 避免发生错误

HttpServletRequest request = null;
HttpServletResponse response = null;
try{
  request  = (HttpServletRequest)req;
  response = (HttpServletResponse)resp;<br>}catch(Exception e){
  throw new RuntimeException("not-http request or response");
}

//控制动态资源不要缓存过滤器
public class NoCacheFilter implements Filter {
 
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
         
//      HttpServletRequest request = (HttpServletRequest)req;
//      HttpServletResponse response = (HttpServletResponse)resp;   不使用该方法
         
        HttpServletRequest request = null;
        HttpServletResponse response = null;
        try{
            request  = (HttpServletRequest)req;
            response = (HttpServletResponse)resp;
        }catch(Exception e){
            throw new RuntimeException("not-http request or response");
        }
        response.setHeader("Expires", "-1");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        chain.doFilter(request, response);
    }
 
    public void destroy() {
 
    }
 
}

动态过滤掉 Servlet 和Jsp

3、静态资源控制缓存时间的过滤器

//控制静态资源的缓存时间
public class StaticResourcesNeedCacheFilter implements Filter {
    private FilterConfig filterConfig;
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = null;
        HttpServletResponse response = null;
        try{
            request  = (HttpServletRequest)req;
            response = (HttpServletResponse)resp;
        }catch(Exception e){
            throw new RuntimeException("not-http request or response");
        }
        long time = 0;//缓存的时间
         
        //根据用户请求的uri地址的后缀:/day19_00_filter/1.html
        String uri  = request.getRequestURI();
        String exName = uri.substring(uri.lastIndexOf(".")+1);
        if("html".equals(exName)){
            String value = filterConfig.getInitParameter("html");//小时
            time = Long.parseLong(value)*60*60*1000;
        }
        if("css".equals(exName)){
            String value = filterConfig.getInitParameter("css");//小时
            time = Long.parseLong(value)*60*60*1000;
        }
        if("js".equals(exName)){
            String value = filterConfig.getInitParameter("js");//小时
            time = Long.parseLong(value)*60*60*1000;
        }
         
        response.setDateHeader("Expires", System.currentTimeMillis()+time);  //Expires 控制时间
        chain.doFilter(request, response);
    }
 
    public void destroy() {
 
    }
 
}

 

4、//*用户自动登录过滤器:

使用了Md5 加密

Base64编码:很重要

编写

//自动登录过滤器
public class AutoLoginFilter implements Filter {
    private  BusinessService s = new BusinessServiceImpl();
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
         
        HttpServletRequest request = null;
        HttpServletResponse response = null;
        try{
            request  = (HttpServletRequest)req;
            response = (HttpServletResponse)resp;
        }catch(Exception e){
            throw new RuntimeException("not-http request or response");
        }
        HttpSession session = request.getSession();
        //判断用户有没有登录:只管没有登录的
        User sUser = (User)session.getAttribute("user");
        if(sUser==null){
            //找loginInfo的cookie:只管找到的
            Cookie cs[] = request.getCookies();
            for(int i=0;cs!=null&&i<cs.length;i++){
                if("loginInfo".equals(cs[i].getName())){
                    //解出用户名(Base64)和密码(MD5)
                    String usernamePassword = cs[i].getValue();
                    String username = usernamePassword.split("_")[0];//base64编码后的
                    String password = usernamePassword.split("_")[1];//MD5加密后的
                    //调用Service再次验证正确性
                    User user = s.login(SecurityUtil.base64decode(username), password);
                    //通过:登录。在HttpSession中设置登录标记
                    if(user!=null){
                        session.setAttribute("user", user);
                    }
                }
            }
        }
        chain.doFilter(request, response);
    }
 
    public void destroy() {
 
    }
 
}

五、过滤器配置的细节

 

六、巩固装饰设计模式

一、装饰

1、编写一个类,实现与被包装类(数据库驱动对Connection的实现)相同的接口。(使这个类和数据库的驱动实现有着相同的行为)

2、定义一个变量,引用被包装类的实例。

3、定义构造方法,传入被包装类的实例。

4、对于要改写的方法,编写自己的代码即可。

5、对于不需要改写的方法,调用原有对象的对应方法。

二、装饰变体(BufferedReader本身就是包装类,对Reader的包装。LineNumberReader,对BufferedReader的包装,还是他的子类)

1、编写一个类,继承已经是包装类的类。

2、定义一个变量,引用被包装类的实例。

3、定义构造方法,传入被包装类的实例。

4、覆盖掉需要改写的方法

七、案例:

1、解决全站中文乱码过滤器

之前解决了 post 的乱码 问题 这里 添加 get的 解决问题

1.定义一个类 EncodingHttpServletRequest 继承 HttpServletRequestWrapper  前对 后 的 包装 得到自己想要的 方法

2.重写  HttpServletRequestWrapper 的 getParameter 方法 。

3.将get传入的值使用 该 super.getCharacterEncoding()的编码 方式返回

如果 使用 get方法 就可以 得到 应有的编码方式

public class SetCharacterEncodingFilter implements Filter {
    private FilterConfig filterConfig;
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
         
        HttpServletRequest request;
        HttpServletResponse response;
        try{
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)resp;
        }catch(Exception e){
            throw new RuntimeException("non-http request or response");
        }
         
        String encoding = filterConfig.getInitParameter("encoding");//用户可能忘记了配置该参数
        if(encoding==null){
            encoding = "UTF-8";//默认编码
        }
         
        request.setCharacterEncoding(encoding);//只能解决POST请求参数的中文问题
        response.setCharacterEncoding(encoding);//输出流编码
        response.setContentType("text/html;charset="+encoding);//输出流编码,通知了客户端应该使用的编码
         
        EncodingHttpServletRequest erequest = new EncodingHttpServletRequest(request);
         
        chain.doFilter(erequest, response);
    }
 
    public void destroy() {
 
    }
 
}
class EncodingHttpServletRequest extends HttpServletRequestWrapper{
    public EncodingHttpServletRequest(HttpServletRequest request){
        super(request);
    }
 
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if(value==null)
            return value;
        //只管get方式
        if("get".equalsIgnoreCase(super.getMethod())){
            try {
                value = new String(value.getBytes("ISO-8859-1"),super.getCharacterEncoding());
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return value;
    }
     
}

2、过滤脏话过滤器

1.新建 DWHttpServletRequest 类 继承  HttpServletRequestWrapper ,

2.包装 getParameter 发方法  过滤 脏话

3.执行 内容  时 得到的是  DWHttpServletRequest 的 request 所以使用的方法是 DWHttpServletRequest的 getParameter。

public class DirtyWordsFilter implements Filter {
 
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
         
        HttpServletRequest request;
        HttpServletResponse response;
        try{
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)resp;
        }catch(Exception e){
            throw new RuntimeException("non-http request or response");
        }
        DWHttpServletRequest dwrequest = new DWHttpServletRequest(request);
        chain.doFilter(dwrequest, response);
 
    }
 
    public void destroy() {
    }
 
}
class DWHttpServletRequest extends HttpServletRequestWrapper{
    private String[] strs = {"禽兽","畜生","傻B","张新鹏"};
    public DWHttpServletRequest(HttpServletRequest request){
        super(request);
    }
 
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if(value==null)
            return value;
         
        for(String s:strs){
            value = value.replace(s, "**");
        }
        return value;
    }
}

3、html标记过滤器

方法和前2种类似

public class HtmlFilter implements Filter {
 
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
         
        HttpServletRequest request;
        HttpServletResponse response;
        try{
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)resp;
        }catch(Exception e){
            throw new RuntimeException("non-http request or response");
        }
        HtmlHttpServletRequest hrequest = new HtmlHttpServletRequest(request);
        chain.doFilter(hrequest, response);
 
    }
 
    public void destroy() {
    }
 
}
class HtmlHttpServletRequest extends HttpServletRequestWrapper{
    public HtmlHttpServletRequest(HttpServletRequest request){
        super(request);
    }
 
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if(value==null)
            return value;
         
        value = htmlFilter(value);//转义字符
        return value;
    }
 
    private String htmlFilter(String message) {
        if (message == null)
            return (null);
 
        char content[] = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuffer result = new StringBuffer(content.length + 50);
        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
            case '<':
                result.append("<");
                break;
            case '>':
                result.append(">");
                break;
            case '&':
                result.append("&");
                break;
            case '"':
                result.append(""");
                break;
            default:
                result.append(content[i]);
            }
        }
        return (result.toString());
    }
}

4、//*全站压缩过滤器(有难度)

public class GzipFilter implements Filter {
 
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request;
        HttpServletResponse response;
        try{
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)resp;
        }catch(Exception e){
            throw new RuntimeException("non-http request or response");
        }
        GzipHttpServletResponse gresponse = new GzipHttpServletResponse(response);
        chain.doFilter(request, gresponse);
        //目标资源执行完毕后执行:要压缩
        byte b[] = gresponse.getBytes();//得到原始的数据为编码的关键点
        System.out.println("压缩前大小:"+b.length);
        //判断客户是否支持gzip压缩
        String acceptEncoding = request.getHeader("Accept-Encoding");
        if(acceptEncoding!=null&&acceptEncoding.contains("gzip")){
            //支持
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            GZIPOutputStream gout = new GZIPOutputStream(out);
            gout.write(b);
            gout.close();
             
            b = out.toByteArray();//压缩后的数据
            System.out.println("压缩后大小:"+b.length);
            //告知浏览器压缩方式
            response.setHeader("Content-Encoding", "gzip");
            response.setContentLength(b.length);//告知客户端,正文的长度
        }
        response.getOutputStream().write(b);
    }
 
    public void destroy() {
 
    }
 
}
class GzipHttpServletResponse extends HttpServletResponseWrapper{
    private ByteArrayOutputStream baos = new ByteArrayOutputStream();//存放截获的数据
     
    private PrintWriter pw = null;
    public GzipHttpServletResponse(HttpServletResponse response){
        super(response);
    }
    //截获输出的数据:放到baos中
    public ServletOutputStream getOutputStream() throws IOException {
        return new MyServletOutputStream(baos);
    }
     
    //字符流:截获放到baos中
    public PrintWriter getWriter() throws IOException {
        pw = new PrintWriter(new OutputStreamWriter(baos, super.getCharacterEncoding()));
        return pw;
    }
    //获取截获的数据
    public byte[] getBytes(){
        try {
            if(pw!=null){
                pw.close();
            }
            baos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return baos.toByteArray();
    }
}
class MyServletOutputStream extends ServletOutputStream{
    private ByteArrayOutputStream baos;
    public MyServletOutputStream(ByteArrayOutputStream baos){
        this.baos = baos;
    }
    public void write(int b) throws IOException {
        baos.write(b);
    }
     
}

 

时间: 2024-09-23 07:15:47

JavaWeb 后端 <十二> 之 过滤器 filter 乱码、不缓存、脏话、标记、自动登录、全站压缩过滤器的相关文章

JavaWeb-过滤器Filter学习(三)实现用户的自动登录与IP黑名单过滤

实现用户的自动登录: 解决方案: 设置一个全站拦截的过虑器. 在此过虑器中,读取用户带过来的Cookie信息,然后从中读取用户的用户名和密码,自动帮助用户登录. 即可实现自动登录功能. 用Filter验证用户是否已经登录过.已经登录过了,我们就根据他选择的自动登录来选择让他在多久内能自动登录. IP黑名单过滤就很简单了,只要在Filter过滤器防范一下就OK. 在init方法中,我们先把黑名单的IP加载进Set<String> set集合, Set集合有如下特点: Java.util.Hash

JavaWeb 后端 &lt;十四&gt; 文件上传下载

1.文件上传与下载 案例:          注册表单/保存商品等相关模块!          --à 注册选择头像 / 商品图片          (数据库:存储图片路径 / 图片保存到服务器中指定的目录) 1.1 文件上传 文件上传,要点: 前台:          1. 提交方式:post          2. 表单中有文件上传的表单项: <input type="file" />          3. 指定表单类型:                    默认类

JavaWeb 后端 &lt;十&gt; 之 数据池 C3P0 DPCB JNDI

一.数据库连接池原理:(理解) //模拟数据库连接池的原理 public class ConnectionPoolDemo {     private static List<Connection> pool = new ArrayList<Connection>();     static{         try {             for(int i=0;i<10;i++){                 Connection conn = JdbcUtil.

⑧javaWeb之在例子中学习(过滤器Filter) 前言

Fitler(过滤器) 过滤器filter是拦截请求,并对传给请求资源的ServletRequest 或 ServletResponse 进行处理的一个对象.可以用于登录,加密和解密,会话检查,图片转换等等   过滤器执行机制图: Filter API : http://docs.oracle.com/javase/6/docs/api/ Filter详解 Filter接口的构成:       所有的Filter类都必须实现javax.servlet.Filter接口.这个接口含有3个过滤器类必

激活引入非线性,池化预防过拟合(深度学习入门系列之十二)

系列文章: 一入侯门"深"似海,深度学习深几许(深度学习入门系列之一) 人工"碳"索意犹尽,智能"硅"来未可知(深度学习入门系列之二) 神经网络不胜语,M-P模型似可寻(深度学习入门系列之三) "机器学习"三重门,"中庸之道"趋若人(深度学习入门系列之四) Hello World感知机,懂你我心才安息 (深度学习入门系列之五) 损失函数减肥用,神经网络调权重(深度学习入门系列之六) 山重水复疑无路,最快下降

Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验

Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 这一章很多,但是很有趣,也是这书的最后一章知识点了,我现在还在考虑要不要写这个拼图和2048的案例,在此之前,我们先来玩玩Android5.X的新特性吧!

Heroku创始人Adam Wiggins发布十二要素应用宣言

Heroku是业内知名的云应用平台,从对外提供服务以来,他们已经有上百万应用的托管和运营经验.前不久,创始人Adam Wiggins根据这些经验,发布了一个"十二要素应用宣言(The Twelve-Factor App)",该宣言由国内工作于安居客的程序员梁山将其翻译为中文,InfoQ中文站摘录如下. 十二要素应用宣言 简介: 如今,软件通常会作为一种服务来交付,它们被称为网络应用程序,或"软件即服务"(SaaS)."十二要素应用程序"(12-F

过滤器 设置乱码无效问题

问题描述 过滤器 设置乱码无效问题 我设置了过滤器想解决乱码问题 过滤失败 另外有下面的报错 信息: Illegal access: this web application instance has been stopped already. Could not load java.lang.Object. The eventual following stack trace is caused by an error thrown for debugging purposes as well

现代“十二要素应用”与Docker

本文讲的是现代"十二要素应用"与Docker,[编者的话] "十二要素应用"为开发SaaS应用提供了方法上的指导,而Docker能够提供打包依赖,解耦后端服务等特性,使得两者非常吻合.这篇文章介绍了Docker特性怎样满足了开发"十二要素应用"的对应要点. Docker非常适合开发"十二要素应用". "十二要素应用"为构建SaaS应用提供了方法论,是由知名PaaS云计算平台Heroku的创始人Adam Wi