这里写目录标题
1 拦截器接口分析
SpringMVC的拦截器Interceptor类似于Javaweb的Filter过滤器
这是 HandlerInterceptor的源码分析
//拦截器就是是一个实现接口HandlerInterceptor的类
public interface HandlerInterceptor {
//在目标方法调用前执行,true是表示放行方法(chain.doFilter()),false表示不放行
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
//目标方法调用后执行,可以通过modelAndView在跳转页面前再添加一些数据
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
//执行该方法需要两个条件 ①目标方法是被放行的状态(preHandle的返回值为true) ②在整个请求完成来到目标页面后
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
2 自定义拦截器过程
①自定义的拦截
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("myInterceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("myInterceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("myInterceptor afterCompletion");
}
}
② 去springmvc.xml配置
<!-- 注册自定义拦截器-->
<mvc:interceptors>
<!-- 配置某个拦截器,默认拦截所有请求;-->
<mvc:interceptor>
<!-- 拦截器的拦截路径-->
<mvc:mapping path="/test3"/>
<bean class="mvc.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
③ 处理器方法
@RequestMapping("/test3")
private String test(){
System.out.println("目标方法执行");
return "restStyle/success";
}
④结果分析
============正常流程=============
输出结果myInterceptor preHandle
目标方法执行
myInterceptor postHandle
跳转到目标页面success
myInterceptor afterCompletion
============异常流程=============
myInterceptor preHandle
这是出异常的目标方法
捕获的异常java.lang.ArithmeticException: / by zero
myInterceptor afterCompletion
⑤执行流程
preHandle方法(返回true放行后) => 处理器的目标方法执行 => postHandle方法执行(可以再添加一些数据) => 页面跳转 => afterCompletion方法
当preHandle的返回值为false的时候整个请求就结束了,那就没有后面的步骤了
即便在处理器目标方法出错不会影响preHandle和 =afterCompletion的执行,但是由于处理器目标方法异常不能正常结束,所以无法调用postHandle,afterCompletion方法可以理解为请求结束页面跳转后执行(出现异常且跳转到错误页面也可以看做是请求的完成)。
3 深入分析Interceptor
![微信截图_20190403164529.png](https://img.php.cn/upload/image/537/366/347/1554281080905775.png)
主要作用:拦截用户请求,进行处理,比如判断用户登录情况、权限验证,只要针对Controller请求进行处理,是通过实现HandlerInterceptor来生效的。Interceptor分两种情况,一种是对会话的拦截,实现spring的HandlerInterceptor接口并注册到mvc的拦截队列中,以下三种方法都是在postHandle返回为true时的情况
- preHandle()方法在调用Handler之前进行拦截(上图步骤2和3之间,顾名思义,该方法将在Controller处理之前进行调用);
- postHandle()方法在视图渲染之前调用(上图步骤4和5之间也就是处理器处理完成但还没有渲染页面的时候调用);
- 该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图(步骤六之后)执行;另一种是对方法的拦截,需要使用@Aspect注解,在每次调用指定方法的前、后进行拦截。
4 Filter与Interceptor区别
Filter介绍
Filter在请求进入servlet容器执行service()方法之前就会经过filter过滤(上图步骤1),不像Intreceptor一样依赖于springmvc框架,只需要依赖于servlet,不像Intreceptor一样依赖于springmvc框架,只需要依赖于servlet。Filter启动是随WEB应用的启动而启动,只需要初始化一次,以后都可以进行拦截。
Filter有如下几个种类:
①用户授权Filter:检查用户请求,根据请求过滤用户非法请求;
②日志Filter:记录某些特殊的用户请求;
③解码Filter:对非标准编码的请求解码。
详细区别
1、实现原理上:Filter是基于函数回调(doFilter()方法)的,而Interceptor则是基于Java反射的(AOP思想)。
2、依赖配置方面:Filter依赖于Servlet容器,直接或注解配置到web.xml中,常用于javaweb开发,而Interceptor不依赖于Servlet容器,只是通过实现HandlerInteceptor接口来定义,用于ssm/springboot开发常见
3、拦截请求范围上:Filter对几乎所有的请求起作用,而Interceptor只能对action请求起作用,也就是被SpringMVC的前端控制器所拦截的路径有效。
4、功能上:Interceptor可以访问Action的上下文,值栈里的对象,可以传值给渲染的页面,这些Filter都不能。
5、生命周期上:在action的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。
6、数据域层面上:Filter在过滤是只能对request和response进行操作,而interceptor可以对request、response、handler、modelAndView、exception进行操作。