zoukankan      html  css  js  c++  java
  • Filter、Listener学习笔记

    Filter 简介

    • Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。
    • 可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Servlet。Servlet 过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。
    • Servlet 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的:
      • 在客户端的请求访问后端资源之前,拦截这些请求。
      • 在服务器的响应发送回客户端之前,处理这些响应。

    Servlet 过滤器方法

    过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类。javax.servlet.Filter 接口定义了三个方法:

    序号 方法 & 描述
    1 public void doFilter (ServletRequest, ServletResponse, FilterChain)

    该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器。
    2 public void init(FilterConfig filterConfig)

    web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
    3 public void destroy()

    Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。

    快速入门

    示例1

    过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明,然后映射到您的应用程序的部署描述符中的 Servlet 名称或 URL 模式。当 Web 容器启动 Web 应用程序时,它会为您在部署描述符中声明的每一个过滤器创建一个实例。Filter的执行顺序与在web.xml配置文件中的配置顺序一致,一般把Filter配置在所有的Servlet之前。

    Input

    web.xml

    <filter>
        <!-- 声明Filter名字 -->
        <filter-name>demo01</filter-name>
        <!-- 对应的Filter类全名 -->
        <filter-class>my.stringbug.FilterDemo01</filter-class>
    </filter>
    
    <filter-mapping>
        <!-- 对应声明的Filter名字 -->
        <filter-name>demo01</filter-name>
        <!-- 过滤器的过滤路径 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    FilterDemo01.java

    public class FilterDemo01 implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) throws IOException, ServletException {
            System.out.println("FilterDemo01 过滤器给执行了 ~~");
    
            // 放行(假如没有放行,那么被该过滤器过滤的页面都不会有请求信息和响应信息)
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() { }
    }
    

    index.jsp

    <body>
      <h1>Demo 01 ~~~~~</h1>
    </body>
    

    Output

    控制台

    FilterDemo01 过滤器给执行了 ~~
    

    浏览器页面

    Demo 01 ~~~~~
    

    示例2

    使用注解的方式进行声明,映射到对应的应用程序的部署描述符中的 Servlet 名称或 URL 模式。

    Input

    FilterDemo02.java

    // "/*" 访问所有资源之前,都会执行该过滤器
    @WebFilter("/*")
    public class FilterDemo02 implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) throws IOException, ServletException {
            System.out.println("FilterDemo02 过滤器给执行了 ~~");
    
            // 放行(假如没有放行,那么被该过滤器过滤的页面都不会有请求信息和响应信息)
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() { }
    }
    

    index.jsp

    <body>
      <h1>Demo 02 ~~~~~</h1>
    </body>
    

    Output

    控制台

    FilterDemo02 过滤器给执行了 ~~
    

    浏览器页面

    Demo 02 ~~~~~
    

    Filter 执行流程 & Filter 生命周期

    Filter 执行流程

    • Filter 接口中有一个doFilter 方法,当咱们编写好 Filter,并配置对哪个 web 资源进行拦截后,web 服务器每次在调用 web 资源的 service 方法之前,都会先调用一下 Filter 的 doFilter 方法,因此,在该方法内编写代码可达到如下的:

      1. 调用目标资源之前,让一段代码执行;
      2. 是否调用目标资源,即是否让用户访问 web 资源;
      3. 调用目标资源之后,让一段代码执行。

    • web 服务器在调用 doFilter 方法时,会传递一个 filterChain 对象进来,filterChain 对象是 filter 接口中最重要的一个对象,它也提供了一个 doFilter 方法,开发人员可以根据需求决定是否调用此方法。如果调用该方法,则 web 服务器就会调用 web 资源的 service 方法,即 web 资源就会被访问;否则的话, web 资源就不会被访问。


    Filter 生命周期

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

    Filter 配置说明

    拦截路径配置

    1. 具体资源路径,如:/index.jsp
    2. 拦截某个目录,如:/directory1/directory2/*
    3. 后缀名拦截,如:*.html
    4. 拦截所有资源,如:/*

    拦截方式配置

    1. 注解配置

      属性 类型 说明
      asyncSupported boolean 指定Filter是否支持异步模式
      dispatcherTypes DispatcherType[ ] 指定Filter对哪种方式的请求进行过滤。
      支持的属性:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST;
      默认过滤所有方式的请求
      filterName String Filter名称
      initParams WebInitParam[ ] 配置参数
      displayName String Filter显示名
      servletNames String[ ] 指定对哪些Servlet进行过滤
      urlPatterns/value String[ ] 两个属性作用相同,指定拦截的路径

    2. web.xml配置

      • <filter>指定一个过滤器。

        • <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
        • <filter-class>元素用于指定过滤器的完整的限定类名。
        • <init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
        • 在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。

      • <filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。

        • 一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
        • <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
        • <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)

      • <servlet-name>指定过滤器所拦截的Servlet名称。

      • <dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARDERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定 Filter 对资源的多种调用方式进行拦截。

        • <dispatcher>子元素可以设置的值及其意义
          1. REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
          2. INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
          3. FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
          4. ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

    过滤器链

    有多个过滤器,过滤器的执行顺序和拦截顺序说明。

    过滤器先后顺序问题

    1. 注解配置:按照类名的字符串比较规则比较,值小的先执行。

      如: AFilter 和 BFilter,AFilter先执行。

    2. web.xml配置:谁定义在上边,谁先执行


    过滤器执行顺序

    如果有两个过滤器:过滤器1和过滤器2

    过滤器1

    @WebFilter(value = "/index.jsp")
    public class FilterDemo04 implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) throws IOException, ServletException {
            System.out.println("小明通过过滤器1,去服务器了");
    
            // Filter1 放行
            filterChain.doFilter(servletRequest, servletResponse);
    
            System.out.println("小明通过过滤器1,从服务器回来了");
        }
    
        @Override
        public void destroy() { }
    }
    

    过滤器2

    @WebFilter(value = "/index.jsp")
    public class FilterDemo05 implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) throws IOException, ServletException {
            System.out.println("小明通过过滤器2,去服务器了");
    
            // Filter2 放行
            filterChain.doFilter(servletRequest, servletResponse);
    
            System.out.println("小明通过过滤器2,从服务器回来了");
        }
    
        @Override
        public void destroy() { }
    }
    

    index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>Filter And Listener Demo</title>
      </head>
      <body>
        <% System.out.println("服务器资源被访问了"); %>
      </body>
    </html>
    

    启动服务器,访问index.jsp资源,控制台输出:

    小明通过过滤器1,去服务器了
    小明通过过滤器2,去服务器了
    服务器资源被访问了
    小明通过过滤器2,从服务器回来了
    小明通过过滤器1,从服务器回来了
    

    Listener 学习笔记

    简介

    监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。监听器可以用来检测网站的在线人数,统计网站的访问量等

    监听器涉及三个组件:事件源事件对象事件监听器

    当事件源发生某个动作的时候,它会调用事件监听器的方法,并在调用事件监听器方法的时候把事件对象传递进去。


    ServletContextListener

    ServletContextListener:监听ServletContext对象的创建和销毁

    void contextDestroyed(ServletContextEvent sce)
    // ServletContext对象被销毁之前会调用该方法
    
    void contextInitialized(ServletContextEvent sce)
    // ServletContext对象创建后会调用该方法
    

    快速入门

    1. 实现ServletContextListener接口
    2. 复写方法
    3. 配置(web.xml配置或注解配置)

    实现ServletContextListener接口,复写方法

    public class ContextLoaderListener implements ServletContextListener {
        /**
         * 监听ServletContext对象创建的。ServletContext对象在服务器启动后自动创建。
         */
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            // ServletContext对象创建后会调用该方法
            System.out.println("ServletContext 对象被创建了");
        }
    
        /**
         * 在服务器关闭后,ServletContext对象被销毁。当服务器正常关闭后,该方法会被执行。
         */
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            // ServletContext对象被销毁之前会调用该方法
            System.out.println("ServletContext 对象被销毁了");
        }
    }
    

    web.xml配置

    <listener>
        <listener-class>my.listener.ContextLoaderListener</listener-class>
    </listener>
    

    注解配置:在实现监听接口的方法上面添加注解

    @WebListener("my/listener/contextLoaderListener")
    

    正常的启动服务器,和关闭服务器:控制台输出

    启动服务器

    ServletContext 对象被创建了
    

    关闭服务器

    ServletContext 对象被销毁了
    

    参考文献

    1. Servlet 编写过滤器 | 菜鸟教程
    2. 详述 Java 中过滤器 Filter 的工作原理及使用方法
    3. Servlet3.0下@WebFilter注解配置Filter
    4. 监听器入门看这篇就够了
    Good Good Write Bug, Day Day Up
  • 相关阅读:
    【网络安全】telnet 登陆远程服务器
    【网络安全】window 快速搭建 ftp 及 多种访问方式
    科普:PCI-E插槽都有哪些样子?
    Memory及其controller芯片整体测试方案(下篇)
    Memory及其controller芯片整体测试方案(上篇)
    超通俗易懂科普:什么是光通信?
    PCB各层介绍及AD软件画PCB时的规则
    第一次接触FPGA至今,总结的宝贵经验
    嵌入式码农的10年Bug调试经验,值得一看
    做嵌入式驱动的,你一定要挺住!
  • 原文地址:https://www.cnblogs.com/liyihua/p/14477576.html
Copyright © 2011-2022 走看看