Filter和Listener-超详细讲解

1、Filter

1.1、过滤器概念

1.1.1、过滤器的基本概念

Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

1.1.2、过滤器的功能

在这里插入图片描述

(1)过滤器可以拦截对资源的访问
(2)一个过滤器可以拦截多个资源,一个资源也可能被多个过滤器拦截
(3)所谓的拦截是根据访问的URL地址来确定访问的是哪个资源,确定是否拦截
(4)所谓的拦截其实就是拦截下来代表请求的request和响应的response
(5)拦截后:控制是否允许访问、访问之前和之外做一些额外操作

1.2、过滤器开发

1.2.1、开发过滤器的两个步骤

过滤器

package cn.tedu.filter;

import javax.servlet.*;
import java.io.IOException;

public class MyFilter01 implements Filter {
    
    

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("拦截器开始拦截");
        //拦截器放行,如果不写,不会往下执行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
    
    
        Filter.super.destroy();
    }
}

Servlet类

public class MyServlet01 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        System.out.println("MyServlet01开始输出");
    }
}

配置xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置servlet-->
    <servlet>
        <servlet-name>myservlet01</servlet-name>
        <servlet-class>cn.tedu.filter.MyServlet01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>myservlet01</servlet-name>
        <url-pattern>/servlet/myservlet01</url-pattern>
    </servlet-mapping>

    
    
    <!--配置过滤器-->
    <filter>
        <filter-name>FirstFilter</filter-name>
        <filter-class>cn.tedu.filter.MyFilter01</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FirstFilter</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
</web-app>    

浏览器访问
在这里插入图片描述

1.3、FilterConfig 类

FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。
Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置息。

FilterConfig 类的作用是获取 filter 过滤器的配置内容

获取 Filter 的名称 filter-name 的内容
获取在 Filter 中 wen.xml 配置的 init-param 初始化参数
获取 ServletContext 对象

过滤器

public class MyFilter01 implements Filter {
    
    

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        //1. 获取 Filter 的名称 filter-name 的内容 (web-xml 中配置的名称)
        System.out.println("filter-name:" + filterConfig.getFilterName());
        //2. 获取在web.xml中配置的 init-param 初始化参数
        System.out.println("初始化参数username的值是:" + filterConfig.getInitParameter("username"));
        System.out.println("初始化参数url的值是:" + filterConfig.getInitParameter("url"));
        //3. 获取 ServletContext 对象
        System.out.println(filterConfig.getServletContext());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("拦截器开始拦截");
        //拦截器放行,如果不写,不会往下执行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
    
    
        Filter.super.destroy();
    }
}

xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置servlet-->
    <servlet>
        <servlet-name>myservlet01</servlet-name>
        <servlet-class>cn.tedu.filter.MyServlet01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>myservlet01</servlet-name>
        <url-pattern>/servlet/myservlet01</url-pattern>
    </servlet-mapping>

    <!--配置过滤器-->
    <filter>
        <filter-name>FirstFilter</filter-name>
        <filter-class>cn.tedu.filter.MyFilter01</filter-class>
        <!--可选的 可以配置多个 过滤器的初始化参数 可以在过滤器中通过FilterConfig对象来获取-->
        <init-param>
            <param-name>name1</param-name>
            <param-value>value1</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>FirstFilter</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
</web-app>  

访问浏览器后输出
在这里插入图片描述

1.3、Filter的生命周期

当服务器启动,web应用加载后,立即创建出这个web应用中的所有过滤器对象,创建出来后立即调用过滤器的init方法执行初始化操作.从此这些过滤器对象驻留在内存中为后续的拦截进行服务.每当拦截到资源时,都会导致dofilter方法执行.最终直到服务器关闭或web应用移除出容器时,随着web应用的销毁,过滤器对象销毁,销毁之前调用destory方法执行善后工作。

2、Listener

2.1、Servlet监听器概述

2.1.1、Servlet监听器概述

JavaEE中提供了八大监听器,用来监听Servlet中指定事件。

2.1.2、Servlet事件监听器步骤

(1)写一个类实现对应接口。
(2)在将写好的监听器类注册到web.xml中。

2.2、监听三个作用域对象创建和销毁的监听器

2.2.1、ServletContextListener详解

ServletContextListener 监听器用于监听 ServletContext 对象的创建和销毁。
ServletContext域的生命周期:
服务器启动,web应用加载后,立即创建代表当前web应用的ServletContext对象,从此驻留在内存中,直到服务器关闭或web应用被移除出容器时,ServletContext对象被销毁。

监听器类ServletContextListener

/**
    ServletContext域:
        生命周期:
            服务器启动web应用加载后立即创建
            之后驻留在内存中唯一的代表当前web应用
            直到服务器关闭或web应用移除出容器是,随着web应用的销毁而销毁
        作用范围:
            整个web应用
        主要功能:
            在web应用范围内共享数据
 */
public class MyServletContextListener implements ServletContextListener {
    
    
    @Override
    public void contextInitialized(ServletContextEvent event) {
    
    
        System.out.println("ServletContext..init.."+event.getServletContext());
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
    
    
        System.out.println("ServletContext..destory.."+event.getServletContext());
    }
}

web.xml

<listener>
        <listener-class>cn.tedu.listener.MyServletContextListener</listener-class>
    </listener>

开启服务器
在这里插入图片描述
关闭服务器
在这里插入图片描述

2.2.2、HttpSessionListener详解

HttpSessionListener监听器用于监听HttpSession对象的创建和销毁。
HttpSession域的生命周期:
在第一次调用request.getSession()方法时创建。
超时过30分钟没人用(此时间可以在web.xml中修改)被销毁。
调用session.invalidate()方法被销毁。
服务器非正常关闭时销毁。
那么,当如果服务器是正常关闭,session会如何处置呢?
未超时的session会以文件的形式保存在服务器中,这个过程叫做session的钝化。在下一次服务器正常启动时,session还可以恢复回来,这个过程叫做session的活化。
*注意:想要随着session被钝化(活化)的对象,他的类必须实现Serializable接口。
作用范围:整个会话范围。

Servlet类

@WebServlet("/servlet/MyServlet01")
public class MyServlet01 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        HttpSession session = request.getSession();
        session.invalidate();
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request,response);
    }
}

监听器类

/**
    session域:
        生命周期
            第一次调用request.getSession()创建
            超时 - 连续30分钟没人使用被销毁
            自杀 - 手动调用session.invalidate()被销毁
            意外身亡 - 服务器非正常关闭时被销毁
        作用范围
            当前会话范围
        主要功能
            在当前会话范围内共享数据
 */
public class MyHttpSessionListener implements HttpSessionListener {
    
    
    @Override
    public void sessionCreated(HttpSessionEvent event) {
    
    
        System.out.println("session..create.."+event.getSession());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
    
    
        System.out.println("session..destory.."+event.getSession());
    }
}

web.xml

<listener>
        <listener-class>cn.tedu.listener.MyHttpSessionListener</listener-class>
    </listener>

在这里插入图片描述

2.2.3、ServletRequestListener 详解

ServletRequestListener监听器用于监听ServletRequest对象的创建和销毁。
ServletRequest对象的生命周期:
请求开始,服务器创建代表这次请求的reuqest对象.
请求结束,服务器销毁代表请求的request对象。

Servlet类

@WebServlet("/servlet/MyServlet04")
public class MyServlet04 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        req.getRequestDispatcher("/servlet/MyServlet01").forward(req,resp);
    }
}

监听器类

/**
    request域:
        生命周期:
            请求开始时创建  请求结束后销毁
        作用范围:
            当前请求范围
        主要功能:
            在当前请求过程中的转发 包含操作中传递数据
 */
public class MyServletRequestListener implements ServletRequestListener {
    
    
    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
    
    
        System.out.println("request..destory..");
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
    
    
        System.out.println("request..init..");
    }
}

web.xml

<listener>
        <listener-class>cn.tedu.listener.MyServletRequestListener</listener-class>
    </listener>

在这里插入图片描述
控制台输出
在这里插入图片描述

2.3、监听域属性变化的监听器

2.3.1、监听域属性变化的监听器

ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener
这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。

2.3.2、监听域属性变化的监听器中的方法

(1)attributeAdded 方法
当向被监听器对象中增加一个属性时,web容器就调用事件监听器的 attributeAdded 方法进行相应,这个方法接受一个事件类型的参数,监听器可以通过这个参数来获得正在增加属性的域对象和被保存到域中的属性对象。
(2)attributeRemoved 方法
当删除被监听对象中的一个属性时,web 容器调用事件监听器的这个方法进行相应。

(3)attributeReplaced 方法
当监听器的域对象中的某个属性被替换时,web容器调用事件监听器的这个方法进行相应。

ServletContextAttributeListener为例

Servlet类

@WebServlet("/servlet/MyServlet02")
public class MyServlet02 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        ServletContext sc = this.getServletContext();
        sc.setAttribute("name","apple");
        sc.setAttribute("name","banana");
        sc.removeAttribute("name");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request, response);
    }
}

监听器类

public class MyServletContextAttributeListener implements ServletContextAttributeListener {
    
    
    @Override
    public void attributeAdded(ServletContextAttributeEvent event) {
    
    
        System.out.println("#属性被加入sc.."+event.getName()+"#"+event.getValue());
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent event) {
    
    
        System.out.println("#属性被移除出sc.."+event.getName()+"#"+event.getValue());
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent event) {
    
    
        System.out.println("#属性被替换在sc.."+event.getName()+"#"+event.getValue()+"#"+event.getServletContext().getAttribute(event.getName()));
    }
}

web.xml

<listener>
        <listener-class>cn.tedu.listener.MyServletContextAttributeListener</listener-class>
    </listener>

在这里插入图片描述

2.4.、监听JAVABEAN在Session域中状态变化的监听器

2.4.1、Javabean在Session中的状态

保存在 Session 域中的对象可以有多种状态:
(1)绑定到 Session 中。
(2)从Session 域中解除绑定。
(3)随Session 被钝化
(4)随Session被活化

2.4.2、监听JAVABEAN在Session域中状态变化的监听器

Servlet 规范中定义了两个特殊的监听器来使javabean感知自己在Session域中状态的变化:
(1)HttpSessionBindingListener接口
实现了HttpSessionBindingListener接口的 JavaBean 对象可以感知自己被绑定到 Session 中和从 Session 中删除的事件。
//当对象被绑定到 HttpSession 对象中时触发
void valueBound(HttpSessionBindingEvent event)
//当对象从 HttpSession 对象中解除绑定时触发
void valueUnbound(HttpSessionBindingEvent event)
(2)HttpSessionActivationListener接口
实现了HttpSessionActivationListener接口的 JavaBean 对象可以感知自己被活化和钝化的事件。
//当绑定到 HttpSession 对象中的对象将要随 HttpSession 对象被钝化时触发
sessionWillPassivate(HttpSessionBindingEvent event)
//当绑定到 HttpSession 对象中的对象将要随 HttpSession 对象被活化时触发
void sessionDidActive(HttpSessionBindingEvent event)方法。

实体类User

public class User implements HttpSessionBindingListener, HttpSessionActivationListener {
    
    
    private String name;
    private int age;
    private String addr;

    public User() {
    
    
    }

    public User(String name, int age, String addr) {
    
    
        this.name = name;
        this.age = age;
        this.addr = addr;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", addr='" + addr + '\'' +
                '}';
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
    
    
        System.out.println("JavaBean自己感知到自己被加入了session..");
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
    
    
        System.out.println("JavaBean自己感知到自己被移除出了session..");
    }

    @Override
    public void sessionWillPassivate(HttpSessionEvent event) {
    
    
        System.out.println("JavaBean自己感知到自己随着session被钝化了..");
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent event) {
    
    
        System.out.println("JavaBean自己感知到自己随着session被活化了..");
    }
}

Servlet类

@WebServlet("/servlet/MyServlet03")
public class MyServlet03 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        HttpSession session = request.getSession();
        User user  = new User();
        session.setAttribute("user",user);
        session.removeAttribute("user");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request,response);
    }
}

浏览器地址输入
在这里插入图片描述
控制台输出
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/stepleavesprint/article/details/127890703
今日推荐