• java:过滤器Filter


    概念

    当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤

    过滤器执行流程

    1. 执行过滤器
    2. 执行放行后的资源
    3. 回来执行过滤器放行代码下边的代码

    注解配置

    只要加上 @WebFilter 注解,并且访问 /* 的时候就会走这里,可以在打印的地方做一些拦截处理。

    执行顺序:先拦截,如果通过的话就去请求资源,请求完资源再去执行放行后面的代码。也就是洋葱圈模型。

    package cn.itcast.web.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    /**
     * 过滤器快速入门程序
     */
    @WebFilter("/*")//访问所有资源之前,都会执行该过滤器
    public class FilterDemo1 implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        	//1、对request对象请求消息增强
            System.out.println("filterDemo1被执行了....");
            //2、放行
            filterChain.doFilter(servletRequest,servletResponse);
            // 3、获取资源(比如请求的一个servlet的jsp页面)
    		// 4、对response对象的响应消息增强
    		System.out.println("filterDemo1回来了...");
    
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    web.xml配置

    web/WEB-INF/web.xml

    <filter>
        <filter-name>demo1filter-name>
        <filter-class>cn.xxx.web.filter.FilterDemo1filter-class>
    filter>
    <filter-mapping>
        <filter-name>demo1filter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    过滤器生命周期方法

    1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
    2. doFilter:每一次请求被拦截资源时,会执行。执行多次
    3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源

    过滤器配置详解

    • 拦截路径配置:
      1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
      2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
      3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
      4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
    • 拦截方式配置:资源被访问的方式
      • 注解配置:
        • 设置dispatcherTypes属性
          1. REQUEST:默认值。浏览器直接请求资源
          2. FORWARD:转发访问资源
          3. INCLUDE:包含访问资源
          4. ERROR:错误跳转资源
          5. ASYNC:异步访问资源
      • web.xml配置
        • 设置 标签即可
    package cn.itcast.web.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    //@WebFilter("/index.jsp") //1. 具体资源路径: /index.jsp   只有访问index.jsp资源时,过滤器才会被执行
    //@WebFilter("/user/*") //2. 拦截目录: /user/*	访问/user下的所有资源时,过滤器都会被执行
    //@WebFilter("*.jsp")   //3. 后缀名拦截: *.jsp		访问所有后缀名为jsp资源时,过滤器都会被执行
    
    //浏览器直接请求index.jsp资源时,该过滤器会被执行
    //@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
    //只有转发访问index.jsp时,该过滤器才会被执行
    //@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
    
    //浏览器直接请求index.jsp或者转发访问index.jsp。该过滤器才会被执行
    //@WebFilter(value="/*",dispatcherTypes ={ DispatcherType.FORWARD,DispatcherType.REQUEST})
    public class FilterDemo5 implements Filter {
    
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println("filterDemo5....");
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
        public void destroy() {
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    过滤器链(配置多个过滤器)

    • 执行顺序:如果有两个过滤器:过滤器1和过滤器2。(洋葱圈模型)

      1. 过滤器1
      2. 过滤器2
      3. 资源执行
      4. 过滤器2
      5. 过滤器1
    • 过滤器先后顺序问题:

      1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
        • 如: AFilter 和 BFilter,AFilter就先执行了。
      2. web.xml配置: 谁定义在上边,谁先执行

    综合例子

    验证其是否登录,如果登录了,则直接放行。如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。

    package cn.itcast.web.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    /**
     * 登录验证的过滤器
     */
    @WebFilter("/*")
    public class LoginFilter implements Filter {
    
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println(req);
            //0.强制转换
            HttpServletRequest request = (HttpServletRequest) req;
    
            //1.获取资源请求路径
            String uri = request.getRequestURI();
            //2.判断是否包含登录相关资源路径,要注意排除掉 css/js/图片/验证码等资源
            if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts/") || uri.contains("/checkCodeServlet")  ){
                //包含,用户就是想登录。放行
                chain.doFilter(req, resp);
            }else{
                //不包含,需要验证用户是否登录
                //3.从获取session中获取user
                Object user = request.getSession().getAttribute("user");
                if(user != null){
                    //登录了。放行
                    chain.doFilter(req, resp);
                }else{
                    //没有登录。跳转登录页面
    
                    request.setAttribute("login_msg","您尚未登录,请登录");
                    request.getRequestDispatcher("/login.jsp").forward(request,resp);
                }
            }
    
    
            // chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
        public void destroy() {
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    综合例子2

    对录入的数据进行敏感词汇过滤,敏感词汇参考《敏感词汇.txt》,如果是敏感词汇,替换为 *** 。

    这里有个难点,我们通过过滤器拿到 req 对象的用户输入值,我们想把这个值替换后再赋值到 req 对象上然后交给 servlet,但是 req 对象没有赋值操作,那么就需要增强 req 对象的 getParameter 方法了,产生一个新的 req 对象。

    package cn.itcast.web.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 敏感词汇过滤器
     */
    @WebFilter("/*")
    public class SensitiveWordsFilter implements Filter {
    
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            //1.创建代理对象,增强getParameter方法
    
            ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //增强getParameter方法
                    //判断是否是getParameter方法
                    if(method.getName().equals("getParameter")){
                        //增强返回值
                        //获取返回值
                        String value = (String) method.invoke(req,args);
                        if(value != null){
                            for (String str : list) {
                                if(value.contains(str)){
                                    value = value.replaceAll(str,"***");
                                }
                            }
                        }
                        
                        return  value;
                    }
    
                    //判断方法名是否是 getParameterMap
    
                    //判断方法名是否是 getParameterValue
    
                    return method.invoke(req,args);
                }
            });
    
            //2.放行
            chain.doFilter(proxy_req, resp);
        }
        private List<String> list = new ArrayList<String>();//敏感词汇集合
        public void init(FilterConfig config) throws ServletException {
    
            try{
                //1.获取文件真实路径
                ServletContext servletContext = config.getServletContext();
                String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
                //2.读取文件
                BufferedReader br = new BufferedReader(new FileReader(realPath));
                //3.将文件的每一行数据添加到list中
                String line = null;
                while((line = br.readLine())!=null){
                    list.add(line);
                }
    
                br.close();
    
                System.out.println(list);
    
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    
        public void destroy() {
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    代理 :https://blog.csdn.net/weixin_43972437/article/details/133687772

  • 相关阅读:
    BT - Unet:生物医学图像分割的自监督学习框架
    C-Pack: Packaged Resources To Advance General Chinese Embedding
    【数字信号去噪】基于matlab麻雀算法优化VMD信号去噪(目标函数为包络熵局部极小值)【含Matlab源码 2111期】
    qt day1
    聚观早报 | 黑五电子产品销售额飙升;谷歌不满微软收购动视暴雪
    Kotlin编程实战——概述(01)
    使用Redis实现文章阅读量、收藏、点赞数量记录功能
    Android 固定WIFI热点路由IP
    25期代码随想录算法训练营第十天 | 栈与队列 part 1
    Gitlab迁移方案
  • 原文地址:https://blog.csdn.net/weixin_43972437/article/details/133685797