JavaSec - Java Web - 三大核心组件 - Listener & Filter

JavaSec - Java Web - 三大核心组件 - Listener & Filter

本篇主要介绍Java Web的其他两大核心组件,Listener和Filter,建议先阅读Servlet篇,对于Java Web的底层组件有一个基础的了解之后,再来进行阅读会更为方便

Filter 过滤器

Filter的主要功能是:

  1. 拦截请求
    • 权限检查
    • 日记操作
    • 事务管理
  2. 过滤响应

Filter过滤器的使用步骤

  1. 编写一个类实现Filter接口(IDEA可以自动生成)
  2. 重写实现 doFilter() 方法(进行过滤)
  3. web.xml或者注解中配置拦截路径

Filter的生命周期

  1. 构造器方法
  2. init初始化方法
    • 第1,2步,在web工程启动的时候执行(Filter已经创建)
  3. doFilter过滤方法
    • 每次拦截到请求,就会执行过滤
  4. destory销毁方法
    • 停止web工程时,销毁Filter过滤器

FilterConfig类

Tomcat每次创建Filter的时候,也会同时创建一个FilterConfig类,其中包含了Filter配置文件的配置信息,其中包含:

  1. 获取Filter的名称 filter-name的内容
  2. 获取再Filter中配置的init-param初始化参数
  3. 获取ServletContext对象

FilterChain 过滤链类

FilterChain顾名思义就是将多个Filter联合使用,形成过滤链

Figure 1: Filter链执行顺序

Figure 1: Filter链执行顺序

Filter的拦截路径

精确匹配
  <url-pattern>/target.jsp<url-pattern>
http://ip:port/%E5%B7%A5%E7%A8%8B%E8%B7%AF%E5%BE%84/target.jsp 单个资源有效
目录匹配
  <url-pattern>/admin/*<url-pattern>
对所有admin目录下的资源访问进行拦截过滤
后缀名匹配
  <url-pattern>*.html<url-pattern>
对所有的html文件进行拦截过滤

Filter过滤器只关心请求的地址是否匹配,不关心请求的资源是否存在!

Listener 监听器

本节内容绝大部分搬运自: Servlet Listener(监听器)

“Servlet 规范中定义了 8 个监听器接口,可以用于监听 ServletContext、HttpSession 和 ServletRequest 对象的生命周期和属性变化事件。开发 Servlet 监听器需要实现相应的监听器接口并重写接口中的方法。”

根据Listener所监听的事件,可以分为3类:

  1. 监听对象 创建和销毁 的监听器;
  2. 监听对象中 属性变更 的监听器;
  3. 监听 HttpSession 中的对象状态改变的监听器;

监听对象创建和销毁的监听器

“Servlet 规范定义了监听 ServletContext、HttpSession、HttpServletRequest 这三个对象创建和销毁事件的监听器,如下表所示:”

Figure 2: 监听对象创建和销毁的监听器

Figure 2: 监听对象创建和销毁的监听器

监听属性变更的监听器

“Servlet 规范定义了监听 ServletContext、HttpSession、HttpServletRequest 这三个对象中的属性变更事件的监听器,这三个监听器接口分别是 ServletContextAttributeListener、HttpSessionAttributeListener 和 ServletRequestAttributeListener。这三个接口中都定义了三个方法,用来处理被监听对象中属性的增加,删除和替换事件。同一种事件在这三个接口中对应的方法名称完全相同,只是参数类型不同,如下表所示:”

Figure 3: 监听属性变更的监听器

Figure 3: 监听属性变更的监听器

监听 Session 中对象状态改变的监听器

“Session 中的对象可以有多种状态:绑定到 Session 中、从 Session 中解除绑定、随 Session 对象持久化到存储设备中(钝化)、随 Session 对象从存储设备中恢复(活化)。”

“Servlet 规范中定义了两个特殊的监听器接口,用来帮助对象了解自己在 Session 中的状态:HttpSessionBindingListener 接口和 HttpSessionActivationListener 接口 ,实现这两个接口的类不需要进行注册。”

Figure 4: 监听 Session 中对象状态改变的监听器

Figure 4: 监听 Session 中对象状态改变的监听器

监听器的注册

注册 Servlet 监听器有 2 种方式,分别是:

  • 在 web.xml 中注册监听器;

  • 使用 @WebListener 注册监听器。

  • 在 web.xml 中注册监听器

在 web.xml 中使用 <listener> 标签配置监听器,Web 容器会自动把监听器注册到事件源中,示例代码如下。

<?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">
    <listener>
        <listener-class>net.biancheng.www.listener.MySessionListener</listener-class>
    </listener>
</web-app>
  1. 使用 @WebListener 注解注册监听器

在监听器类上使用 @WebListener 注解,可以将该 Java 类注册为一个监听器类。示例代码如下。

package net.biancheng.www.servlet;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* 监听器实例代码
*
* @author 编程帮 www.biancheng.net
*/
@WebListener
public class MyListener implements ServletContextListener {
    public MyListener() {
    }
    public void contextDestroyed(ServletContextEvent sce) {
    }
    public void contextInitialized(ServletContextEvent sce) {
    }
}

三个组件的调用顺序

三者的加载顺序为Listener->Filter->Servlet

在org.apache.catalina.core.StandardContext类的 startInternal() 方法中,

依次调用了listenerStart(), filterStart(),最后是loadOnStartup();

这三处调用触发了Listener、Filter、Servlet的构造加载。

protected synchronized void startInternal() throws LifecycleException {
            ... ...
        try {
            ... ...
            // 1. ListenerStart()
            if (ok && !this.listenerStart()) {
                log.error(sm.getString("standardContext.listenerFail"));
                ok = false;
            }

            // 2. filterStart()
            if (ok && !this.filterStart()) {
                log.error(sm.getString("standardContext.filterFail"));
                ok = false;
            }
            // 3. loadOnStartup()
            if (ok && !this.loadOnStartup(this.findChildren())) {
                log.error(sm.getString("standardContext.servletFail"));
                ok = false;
            }

            super.threadStart();
            ... ...
    }

Reference

【尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版】

Servlet Listener(监听器)

Java安全学习——Tomcat架构浅析

Licensed under CC BY-NC-SA 4.0
Last updated on Oct 26, 2022 08:14 CST
comments powered by Disqus
Cogito, ergo sum
Built with Hugo
Theme Stack designed by Jimmy