JavaSec - Java Web - 三大核心组件 - Listener & Filter
本篇主要介绍Java Web的其他两大核心组件,Listener和Filter,建议先阅读Servlet篇,对于Java Web的底层组件有一个基础的了解之后,再来进行阅读会更为方便
Filter 过滤器
Filter的主要功能是:
- 拦截请求
- 权限检查
- 日记操作
- 事务管理
- …
- 过滤响应
Filter过滤器的使用步骤
- 编写一个类实现Filter接口(IDEA可以自动生成)
- 重写实现
doFilter()
方法(进行过滤) - web.xml或者注解中配置拦截路径
Filter的生命周期
- 构造器方法
- init初始化方法
- 第1,2步,在web工程启动的时候执行(Filter已经创建)
- doFilter过滤方法
- 每次拦截到请求,就会执行过滤
- destory销毁方法
- 停止web工程时,销毁Filter过滤器
FilterConfig类
Tomcat每次创建Filter的时候,也会同时创建一个FilterConfig类,其中包含了Filter配置文件的配置信息,其中包含:
- 获取Filter的名称 filter-name的内容
- 获取再Filter中配置的init-param初始化参数
- 获取ServletContext对象
FilterChain 过滤链类
FilterChain顾名思义就是将多个Filter联合使用,形成过滤链
Filter的拦截路径
- 精确匹配
- 对http://ip:port/%E5%B7%A5%E7%A8%8B%E8%B7%AF%E5%BE%84/target.jsp 单个资源有效
<url-pattern>/target.jsp<url-pattern>
- 目录匹配
- 对所有admin目录下的资源访问进行拦截过滤
<url-pattern>/admin/*<url-pattern>
- 后缀名匹配
- 对所有的html文件进行拦截过滤
<url-pattern>*.html<url-pattern>
Filter过滤器只关心请求的地址是否匹配,不关心请求的资源是否存在!
Listener 监听器
本节内容绝大部分搬运自: Servlet Listener(监听器)
“Servlet 规范中定义了 8 个监听器接口,可以用于监听 ServletContext、HttpSession 和 ServletRequest 对象的生命周期和属性变化事件。开发 Servlet 监听器需要实现相应的监听器接口并重写接口中的方法。”
根据Listener所监听的事件,可以分为3类:
- 监听对象
创建和销毁
的监听器; - 监听对象中
属性变更
的监听器; - 监听
HttpSession
中的对象状态改变的监听器;
监听对象创建和销毁的监听器
“Servlet 规范定义了监听 ServletContext、HttpSession、HttpServletRequest 这三个对象创建和销毁事件的监听器,如下表所示:”
监听属性变更的监听器
“Servlet 规范定义了监听 ServletContext、HttpSession、HttpServletRequest 这三个对象中的属性变更事件的监听器,这三个监听器接口分别是 ServletContextAttributeListener、HttpSessionAttributeListener 和 ServletRequestAttributeListener。这三个接口中都定义了三个方法,用来处理被监听对象中属性的增加,删除和替换事件。同一种事件在这三个接口中对应的方法名称完全相同,只是参数类型不同,如下表所示:”
监听 Session 中对象状态改变的监听器
“Session 中的对象可以有多种状态:绑定到 Session 中、从 Session 中解除绑定、随 Session 对象持久化到存储设备中(钝化)、随 Session 对象从存储设备中恢复(活化)。”
“Servlet 规范中定义了两个特殊的监听器接口,用来帮助对象了解自己在 Session 中的状态:HttpSessionBindingListener 接口和 HttpSessionActivationListener 接口 ,实现这两个接口的类不需要进行注册。”
监听器的注册
注册 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>
- 使用 @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();
... ...
}