过滤器、监听器、拦截器
过滤器、拦截器的恩怨情仇
1. 关系图
过滤器
过滤器是在请求进入tomcat容器后,但请求进入servlet之前进行预处理。请求的返回结果也是在servlet处理完成后,返回给前端使用。
作用:
可以对对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截(静态文件,跟用户没有关系的内容),从而实现一些特殊的功能。例如实现URL级别的权限访问控制(URL级别的权限,跟用户细致的权限无关)、过滤敏感词汇、压缩响应信息、字符集统一等一些高级功能。
理解的方式:
//Filter 的 doFilter 方法
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//对应上图的Filter pre
System.out.println("before...");
//进入servlet doService()或service();
chain.doFilter(request, response);
// 对应上图的 FilterAfter 有时我们不会对此编程,但你返回的时候可以对返回结果在此进行处理。
System.out.println("after...");
}
拦截器(AOP)
从上图我们可以看出过滤器只在servlet前后起作用,所以它既不能捕获异常,获得bean对象等,这些是只能是进入servlet里面的拦截器能过做到。拦截器中用于在某个方法或字段被访问之前,进行拦截然后,在之前或之后加入某些操作。
作用:比如日志,安全(日志因为要对每一个请求的方法做拦截、具体到每一个类的,对于较为细致的权限,用拦截器)等。一般拦截器方法都是通过动态代理的方式实现。可以通过它来进行权限验证,或者判断用户是否登陆,或者是像12306 判断当前时间是否是购票时间。
代码创建和使用
拦截器遇到的问题
无法注入@autowried:解决方法
出现原因其实就是此类是在bean加载之前被调用,或者springboot在加载时没有识别到此类,所以注入为空,要想使此类被识别到,那么就要在启动时被spring识别到,需要将其变为bean对象并被识别到。
是因为你的拦截器中的 new MyInterceptor() ,spring 没有将 Interceptor 注册为 bean
监听器
定义
listener是servlet规范中定义的一种特殊类。用于监听servletContext、HttpSession和servletRequest等域对象的创建和销毁事件。监听域对象的属性发生修改的事件。用于在事件发生前、发生后做一些必要的处理。其主要可用于以下方面:1、统计在线人数和在线用户2、系统启动时加载初始化信息3、统计网站访问量4、记录用户访问路径。
常用的监听器 servletContextListener、httpSessionListener、servletRequestListener)
实现方式
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class RequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
// TODO Auto-generated method stub
System.out.println("======销毁监听器========");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("======进入监听器========");
}
对比
图示
具体区别
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
- 拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。
- 拦截器只能对action请求起作用,而过滤器可以对几乎所有请求起作用
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。