• java-1115


    Filter:过滤器

    1. 概念:

      1. web过滤器:拦截浏览器的请求,完成一些特殊功能。
      2. 过滤器作用:一般用于完成通过的操作。(例如帮助服务器检查一些字段是否携带,比如访问界面的时候需要带token,否则返回登录界面)
    2. 快速入门:

      1. 步骤:
        1. 定义一个类,实现接口Filter
        2. 复写方法
        3. 配置拦截路径(定义访问什么资源的时候,过滤器生效),两种配置方法
          1. Web.xml
          2. 注解 @WebFilter( )我们需要配置里面的urlPatten这个属性,这个属性等于value,所以可以省略不写。
            1. @WebFilter(“/*”) 代表访问所有资源的时候都会拦截
    3. 过滤器细节:

      1. web.xml配置

        <filter>
            <filter-name>demo1filter-name>
            <filter-class>com.emnets.java1115.Filter.FilterDemo1filter-class>
        filter>
        <filter-mapping>
            <filter-name>demo1filter-name>
            <url-pattern>/*url-pattern>
        filter-mapping>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
      2. 过滤器的执行流程

        1. doFilter方法中:req就是请求参数,

          1. 首先执行chain.doFilter(req,resp)方法之前的代码,可能会有一些对req参数的校验,如果通过就放行
          2. chain.doFilter(req,resp) 这个方法是放行方法,就是让服务器去处理请求
          3. 执行完放行后会回到chain.doFilter(req,resp)这个方法的下一行代码继续执行。
          //  对request对象的请求消息增强
          System.out.println("filterDemo2...");
          //  放行
          chain.doFilter(request, response);
          //  对response对象的响应消息增强
          System.out.println("filterDemo2 executing!");
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
      3. 过滤器生命周期方法

        1. init方法:服务器启动后会创建Filter对象,然后调用init方法,服务器自动完成(仅执行一次)用于加载资源
        2. doFilter方法:每一次请求被拦截资源时会执行,方法内包含拦截的逻辑
        3. destroy方法:服务器关闭之后。Filter对象被销毁。如果服务器正常关闭,则会执行destroy(仅执行一次)释放资源
      4. 过滤器的配置详解(两种配置)

        1. 拦截路径配置:

          1. “/*”:拦截所有资源
          2. “/资源”:具体资源路径,只有访问资源时过滤器才会执行,使用较少。
          3. “/user/*”:目录拦截,访问user目录下的所有资源时,过滤器都会执行。
          4. “*.jsp”:后追拦截,访问所有后缀名为jsp的资源时,过滤器都会拦截。
        2. 拦截方式配置:资源访问的方式(直接请求、转发是两种不同的方式)

          1. 注解配置:设置dispatcherTypes的属性

            1. REQUEST:默认值,浏览器直接请求资源(重要)
            2. FORWARD:转发访问资源(重要)
            3. INCLUDE:包含访问资源
            4. ERROR:错误跳转资源
            5. ASYNC:异步访问资源
          2. 注解配置多个值:

            1. @WebFilter(value = "/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
              
              • 1
          3. web.xml配置方式:

            1.    <filter>
                      <filter-name>demo1filter-name>
                      <filter-class>com.emnets.java1115.Filter.FilterDemo1filter-class>
                  filter>
                  <filter-mapping>
                      <filter-name>demo1filter-name>
                      <url-pattern>/*url-pattern>
                      <dispatcher>FORWARDdispatcher>
                      <dispatcher>REQUESTdispatcher>
                  filter-mapping>
              
              • 1
              • 2
              • 3
              • 4
              • 5
              • 6
              • 7
              • 8
              • 9
              • 10
          4. 思考题:如果同时配置了请求和转发的过滤,那么一次请求触发的转发会触发几次过滤器

            1. 答案:2次 ,请求和转发分别都会触发过滤器
            2. 理解:虽然是一次请求,但是在服务器内部进行了跳转,每次切换资源都会触发过滤器
      5. 过滤器链(配置多个过滤器)

        1. 执行顺序 :如果有两个过滤器:f1 和 f2
          1. f1执行
          2. f2执行
          3. 资源执行
          4. f2回来执行
          5. f1回来执行
        2. 过滤器设计的先后顺序:
          1. 注解配置:按照类名的字符串比较规则比较,值小的先执行,
            1. 例如:AFilter 和 BFilter比较,A先执行
          2. web.xml配置: 谁定义在上面,谁先执行
      6. 案例一:登录验证

        1. 步骤:
          1. 排除登录相关的资源,
            1. 是:直接放行
            2. 不是:判断是否已经登录
              1. 未登录:
              2. 已登录:
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        
            //  0.强制转换
            HttpServletRequest request = (HttpServletRequest)req;
            
            //  1.获取请求资源的请求路径
            String requestURI = request.getRequestURI();
        
            //  2.判断是否包含登录相关
            //  2.1 同时还要注意排除各种css/js/图片/验证码等资源
            if(requestURI.contains("/login.jsp")||requestURI.contains("/loginServlet")
                    ||requestURI.contains("/css/*")||requestURI.contains("/js/*")||requestURI.contains("/checkCodeServlet")){
                //  放行登录
                chain.doFilter(req, resp);
            }else {
                //  3.session获取
                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);
                }
            }
        
        }
        
        • 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
      7. 代理模式

        1. 理解:在运行期间,对象中方法的动态拦截,在拦截前后执行功能操作,而原有对象不改变

        2. 概念:

          1. 真实对象:被代理的对象
          2. 代理对象:
          3. 代理模式:代理对象去代理真实对象,达到增强真是对象功能的目的
        3. 实现方式:(区别在于代理对象的生成方式)

          1. 静态代理:由一个类文件描述代理模式
          2. 动态代理:在内存中形成代理类(看不到一个真正的类文件,会在内存中动态生成)
            1. 实现步骤:
              1. 代理对象和真实对象实现相同的接口
              2. 代理对象 = Proxy.newProxyInstance( );进行代理对象的获取
              3. 使用代理对象调用方法。
              4. 增强方法
          3. 动态代理代码:
          public class ProxyTest {
          
              /**
               *
               * @param args
               */
              public static void main(String[] args) {
                  //  1.创建真实对象
                  Lenovo lenovo = new Lenovo();
          
                  /**
                   *   2.动态代理增强lenovo对象
                   *   三个参数:
                   *      1.类加载器 : 真实对象.getClass().getClassLoader()
                   *      2.接口数组 : 真实对象.getClass().getInterfaces()
                   *      3.处理器   :
                   */
                  SaleComputer proxy_lenovo = (SaleComputer)Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
                      /**
                       * 代理逻辑编写的方法:代理对象调用的所有方法,都会触发该方法执行。
                       * 增强代码的逻辑就会在这个方法中执行
                       * @param proxy 代理对象,就是指proxy_lenovo这个对象,一般不用
                       * @param method 代理对象调用的方法会封装成对象,变成参数传递进来
                       * @param args 代理对象调用方法时,传递的实际参数,封装进args,这里面就会有8000这种参数
                       * @return
                       * @throws Throwable
                       */
                      @Override
                      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                          System.out.println("该方法执行了.....");
                          System.out.println(method.getName());
                          return null;
                      }
                  });
          
                  //  3.调用方法
                  String  computer = proxy_lenovo.sale(8000);
                  System.out.println(computer);
              }
          }
          
          • 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
        4. invoke方法的写法

          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          
                 //  相当于使用真实对象调用该方法
                 Object obj = method.invoke(lenovo, args);
          
                 //  思考:方法应该如何增强
          
                 //  这个返回值就是调用了方法后接收的返回值,会根据操作方法的不同而完全不同。
                 return obj;
          }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
        5. 方法增强方式:

          1. 增强参数列表

            @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            
                            //  首先判断方法是否是需要增强的方法
                            if(method.getName().equals("sale")){
                                //  1.增强参数
                                double money = (double) args[0];
                                money *= 0.85;
                                Object obj = method.invoke(lenovo, money);
                                return obj;
                            }else {
                                
                                //  相当于使用真实对象调用该方法
                                Object obj = method.invoke(lenovo, args);
            
                                //  这个返回值就是调用了方法后接收的返回值,会根据操作方法的不同而完全不同。
                                return obj;
                            }
            
                        }
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
          2. 增强返回值类型

             @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            
                            //  首先判断方法是否是需要增强的方法
                            if(method.getName().equals("sale")){
                                //  1.增强返回值
                                double money = (double) args[0];
                                money *= 0.85;
                                String obj = (String)method.invoke(lenovo, money);
                                return obj+"_鼠标垫";
                            }else {
                                //  相当于使用真实对象调用该方法
                                Object obj = method.invoke(lenovo, args);
                                //  这个返回值就是调用了方法后接收的返回值,会根据操作方法的不同而完全不同。
                                return obj;
                            }
                        }
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
          3. 增强方法体执行逻辑

            @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            
                            //  首先判断方法是否是需要增强的方法
                            if(method.getName().equals("sale")){
                                //  1.增强返回值
                                double money = (double) args[0];
                                money *= 0.85;
                                System.out.println("专车接你....");
                                String obj = (String)method.invoke(lenovo, money);
                                System.out.println("免费送货....");
                                return obj+"_鼠标垫";
                            }else {
                                //  相当于使用真实对象调用该方法
                                Object obj = method.invoke(lenovo, args);
                                //  这个返回值就是调用了方法后接收的返回值,会根据操作方法的不同而完全不同。
                                return obj;
                            }
                        }
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
      8. 案例二:过滤敏感词汇

        1. 需求:
          1. 对录入数据的敏感词汇进行过滤
          2. 敏感词汇为“笨蛋”、“坏蛋”
          3. 如果是敏感词汇,替换为“***”
        2. 分析:
          1. 对request对象的getParameter方法进行增强,增强获取参数相关方法
          2. 放行。传递代理对象
        /**
         * 敏感词汇过滤器
         */
        
        @WebFilter("/*")
        public class SensitiveWordsFilter implements Filter {
        
            private List<String> list = new ArrayList<String>();    //  敏感词汇
        
            public void init(FilterConfig config) throws ServletException {
        
                try {
                    //  加载文件,获取文件真实路径
                    ServletContext servletContext = config.getServletContext();
                    String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
                    //  读取文件
                    BufferedReader br = new BufferedReader(new FileReader(realPath));
                    //  将文件的每一行数据添加到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() {
            }
        
            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        
                //  1.创建代理对象,增强getParameter方法
                ServletRequest proxy_req = (ServletRequest)Proxy.newProxyInstance(request.getClass().getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
                        if(method.getName().equals("getParameter")){
                            //  增强返回值
                            //  获取返回值,对返回值进行过滤
                            String value = (String)method.invoke(request, args);
                            if(value!=null){
                                for(String str:list){
                                    if(value.contains(str)){
                                        value = value.replaceAll(str,"***");
                                    }   // if
                                }   //for
        
                            }// if
                            return value;
                        }
                        return method.invoke(request,args);
                    }
                });
        
                //  2.放行,传递代理对象
        
        
                chain.doFilter(proxy_req, response);
            }
        }
        
        • 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

        为了测试编写了一个servlet一起运行:

        @WebServlet("/testServlet")
        public class TestServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                this.doPost(request, response);
            }
        
            @Override
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                String name = request.getParameter("name");
                String msg = request.getParameter("msg");
                System.out.println(name+" : "+msg);
        
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
      9. 补充了对getParameterMap方法的增强:

        @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        
                //  1.创建代理对象,增强getParameter方法
                ServletRequest proxy_req = (ServletRequest)Proxy.newProxyInstance(request.getClass().getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
                        if(method.getName().equals("getParameter")){
                            //  增强返回值
                            //  获取返回值,对返回值进行过滤
                            String value = (String)method.invoke(request, args);
                            if(value!=null){
                                for(String str:list){
                                    if(value.contains(str)){
                                        value = value.replaceAll(str,"***");
                                    }   // if
                                }   //for
        
                            }// if
                            return value;
                        }else if(method.getName().equals("getParameterMap")){
                            Map<String, String[]> parameterMap = (Map<String, String[]>)method.invoke(request,args);
                            if(!parameterMap.isEmpty()){
                                // 遍历参数列表
                                for(String[] p_value: parameterMap.values()){
                                    //  判断是否有子参数
                                    if(p_value.length>0){
                                        //  遍历子参数
                                        for(int i=0;i<p_value.length;i++){
                                            //  遍历敏感词汇
                                            for(String str:list){
                                                //  判断是否含有敏感词汇
                                                if(p_value[i].contains(str)){
                                                    //  有则替换
                                                    p_value[i] = p_value[i].replaceAll(str,"***");
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            return parameterMap;
                        }
                        return method.invoke(request,args);
                    }
                });
        
                //  2.放行,传递代理对象
        
        
                chain.doFilter(proxy_req, response);
            }
        
        • 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

    Listener:监听器

    1. 概念:web的三大组件之一。

      1. 事件监听机制:
        1. 事件 :一件事情
        2. 事件源 :事件发生的地方
        3. 监听器 :一个对象
        4. 注册监听:将事件、事件源、监听器绑定在一起。当事件源上发生某个事件后,执行监听器代码。
    2. ServletContextListener:监听ServletContext对象的创建和销毁

      1. void contextDestory(ServletContextEvent sce): servletContext对象被销毁前会调用
      2. void contextInitialized(ServletContextEvent sce):servletContext创建之后会调用该方法
    3. 步骤:

      1. 定义一个类,实现servletContextListener接口

      2. 复写方法

      3. 配置

        1. web.xml方式

           <listener>
                  <listener-class>com.emnets.java1115.listener.ContextLoaderListenerlistener-class>
              listener>
          
          • 1
          • 2
          • 3
        2. 注解方式

          @WebListener
          
          • 1
    4. 代码:

      public class ContextLoaderListener implements ServletContextListener {
      
          /**
           * 监听servletContext对象创建。ServletContext对象服务器启动后自动创建。
           * @param sce
           */
          @Override
          public void contextInitialized(ServletContextEvent sce) {
      
              //  1.获取servletContext对象
              ServletContext servletContext = sce.getServletContext();
      
              //  2.加载资源文件
              String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
      
              //  3.获取真实路径
              String realPath = servletContext.getRealPath(contextConfigLocation);
      
              //  4.加载进内存
              try {
                  FileInputStream fis = new FileInputStream(realPath);
                  System.out.println(fis);
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              }
      
              System.out.println("servletContext对象被创建了");
          }
      
      
          /**
           * 服务器关闭后,ServletContext对象被销毁,当服务器正常关闭后该方法被调用
           * @param sce
           */
          @Override
          public void contextDestroyed(ServletContextEvent sce) {
              System.out.println("ServletContext对象被销毁了");
          }
      }
      
      
      • 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
  • 相关阅读:
    怎么设置IP白名单
    Qt 子窗口不设置parent时,如何随主窗口关闭
    python API自动化(Pytest+Excel+Allure完整框架集成+yaml入门+大量响应报文处理及加解密、签名处理)
    java个人资金账户管理计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    零基础入门JavaWeb——正则表达式
    错误-maven工程,程序包org.apache.commons.xxx不存在,Java:不支持发行版本5
    蓝桥等考Python组别十五级004
    lec formality inconclusive举例
    赶紧进来看看---万字讲解C/C++中的自定义类型:结构体
    报表开发工具Reports and Dashboards新版本2022.3发布|附下载
  • 原文地址:https://blog.csdn.net/lannister_awalys_pay/article/details/127876342