过滤器
Filter过滤器简介
Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器。Filter 过滤器是 JavaEE 的规范,也就是接口。Filter过滤器主要是用于拦截请求,过滤响应的。结合过滤器可以进行权限检查、编码控制、事务管理等操作。
过滤器三要素
1拦截
过滤器之所以能够对请求进行预处理,关键是对请求进行拦截,把请求拦截下来才能够做
后续的操作。而且对于 个具体的过滤器,它必须明确它要拦截的请求,而不是所有请求
都拦截。
2过滤
根据业务功能实际的需求,看看在把请求拦截到之后,需要做什么检查或什么操作,写对
应的代码即可。
3放行
过滤器完成自己的任务或者是检测到当前请求符合过滤规则,那么可以将请求放行。所谓
放行,就是让请求继续去访问它原本要访问的资源。
自定义Filter
实现Filter接口
首先自定义过滤器需要实现javax.servlet.Filter接口。实现其中doFilter方法如下(其中init和destroy方法已经有默认实现):
@WebFilter("/demo01.do")
public class Demo01Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("helloA");
//放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("helloA2");
}
@Override
public void destroy() {
}
}
init(FilterConfig)方法:初始化自定义Filter,它与Servlet的init方法作用是一样的,FilterConfig于ServletConfig也类似,利用这两个对象都可以获得容器的环境类ServletContext对象,FilterConfig也可以取到<filter>下配置的<init-param>参数值。注意web工程启动时就会执行其构造方法和init(FilterConfig)方法。(Filter已创建和初始化完成)
doFilter(ServletRequest,ServletResopnse,FilterChain)方法:在每个用户请求进来时这个方法都会被调用,并且在Servlet的service方法之前被调用。而FilterChain就代表当前的整个请求链,所以通过调用FilterChain对象的doFilter方法可以将请求传递给下一个过滤器。如果想拦截这个请求,可以不调用FilterChain对象的doFilter方法,那么这个请求将被直接返回。这是一种职责链模式。
destory()方法:当停止 web 工程的时候,就会执行该方法,用于释放当前Filter对象所占用的资源,这个方法将在Filter对象真正被销毁之前被调用。注意,当web容器调用这个方法之后,容器会再调用一次doFilter方法。
多个Filter的执行特点
多个Filter过滤器一起执行的特点:
所有Filter和目标资源都默认在同一线程中;
多个Filter共同执行的时候,他们都使用同一个request对象;
如果使用web.xml对Filter进行配置,那么多个Filter的执行的优先顺序<filter-mapping>的由上到下的配置顺序决定的,先配置的先执行;
使用注解配置Filter的话,filter的执行顺序跟名称的字母顺序有关,例如AFilter会比BFilter先执行。
如果既在web.xml中配置了,也通过注解配置了,那么会优先执行web.xml中配置的Filter
Filter执行流程
整体工作流程
(1)客户端浏览器发送请求访问容器指定的 Web 资源
(2)Servlet 容器接收请求,并针对本次的请求分别创建一个 request 对象和 response 对象
(3)请求到达 Web 资源之前,先读取 web.xml 或 @WebFilter 的配置信息对所有的过滤器进行加载和实例化。先调用 Filter 的 doFilter() 方法,检查 request 对象,对请求进行预处理操作。
(4)在 Filter 的 doFilter() 方法内,调用 FilterChain.doFilter() 方法,将请求传递给下一个过滤器或目标资源。如果不放行,将无法访问Servlet资源以及响应数据给客户端浏览器,界面将显示空白页面。
(5)目标资源生成响应信息返回客户端之前,处理控制权会再次回到 Filter 的 doFilter() 方法,执行 FilterChain.doFilter() 后的语句,检查 response 对象,可进行修改响应头和响应正文。
(6)响应信息返回客户端浏览器
过滤器Filter执行步骤
- 放行前逻辑 : 对request数据进行处理
- 放行,访问资源
- 放行后逻辑 : 对response数据进行处理
public class filterTest 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("放行前逻辑");
//放行 使用FilterChain接口实现类对象调用doFilter()方法
filterChain.doFilter(servletRequest, servletResponse);
//放行后逻辑
System.out.println("放行后逻辑");
}
@Override
public void destroy() {
}
}
Filter配置方式
1.web.xml配置
<filter>
<!--<!– 配置Filter的好友名称–>-->
<filter-name>Demo01Filter</filter-name>
<!--<!–Filter的全类名,便于ServLet容器创建Filter对象 –>-->
<filter-class>filters.Demo01Filter</filter-class>
</filter>
<filter-mapping>
<!--<!– 配置Filter要拦截的山标资源 –>-->
<filter-name>Demo01Filter</filter-name>
<url-pattern>/demo01.do</url-pattern>
</filter-mapping>
2.注释配置
在Filter的自定义类增加@WebFilter注解
@WebFilter(filterName = "testFilter",urlPatterns = "/TestServlet",initParams = @WebInitParam(name = "name",value = "ABC123456"),dispatcherTypes = DispatcherType.REQUEST)
public class TestFilter implements Filter {
...
}
Filter生命周期
(1) 初始化阶段 Servlet 容器负责加载和实例化 Filter。容器启动时,读取 web.xml 或 @WebFilter 的配置信息对所有的过滤器进行加载和实例化。 加载和实例化完成后,Servlet 容器调用 init() 方法初始化 Filter 实例。在 Filter 的生命周期内, init() 方法只执行一次。
(2) 拦截和过滤阶段 该阶段是 Filter 生命周期中最重要的阶段。当客户端请求访问 Web 资源时,Servlet 容器会根据 web.xml 或 @WebFilter 的过滤规则进行检查。当客户端请求的 URL 与过滤器映射匹配时,容器将该请求的 request 对象、response 对象以及 FilterChain 对象以参数的形式传递给 Filter 的 doFilter() 方法,并调用该方法对请求/响应进行拦截和过滤。
(3) 销毁阶段 Filter 对象创建后会驻留在内存中,直到容器关闭或应用被移除时销毁。销毁 Filter 对象之前,容器会先调用 destory() 方法,释放过滤器占用的资源。在 Filter 的生命周期内,destory() 只执行一次。
监听器
概念
Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以监听某个对象的状态变化的组件,比如监听在线的用户的数量。
事件源:SerlvetConext,HttpSession和ServletRequest这三个域对象
监听源:监听事件源对象,事件源对象状态的变化都会触发监听源
响应行为:监听器监听到事件源的状态变化时,对其进行采取的功能行为
监听器分类
监听器有三种,分为监听生命周期、监听对象属性值变化与监听Session 内的对象
(1)监听生命周期
HttpSessionLister、ServletContextListener、ServletRequestListener
(2)监听对象属性值变化
HttpSessionAttributeLister、ServletContextAttributeListener、ServletRequestAttributeListener
(3)监听Session 内的对象
HttpSessionBindingListener 和 HttpSessionActivationListener
注意:与上面六类不同,这两类 Listener 监听的是Session 内的对象,而非 Session 本身,不需要在 web.xml中配置。
package listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyServletContextListener implements ServletContextListener {
//Servlet上下文对象初始化动作被监听
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Servlet上下文对象初始化动作被监听");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Servlet上下文对象销毁动作被监听到了");
}
}
配置监听器
1.在web.xml中配置listner标签
<listener>
<listener-class>listener.MyServletContextListener</listener-class>
</listener>
2.在类使用注解@WebListener
@WebListener
public class MyHttpSessionLister implements HttpSessionListener {
......
}
监听生命周期HttpSession
HttpSessionListener用来监听HttpSession对象的创建和销毁,实时监听WEB 程序中的活动会话的数量,常用在网站在线人数的精准统计。