简介
在springMVC中我们可以自定义拦截器来对请求进行拦截,进行相应的处理
拦截器执行流程
拦截器是一个接口,里面有3个方法
- preHandle:在目标handler执行前调用
- postHandle:在目标handler执行完成后进行调用
- afterCompletion:在视图渲染后调用
示意图如下
基本使用
首先创建一个类,实现HandlerInterceptor接口
@Component
public class MyInterceptor01 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("调用preHandle方法");
//返回false不会执行目标方法
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("调用postHandle方法");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("调用afterCompletion方法");
}
}
创建一个handler
@RequestMapping("/member")
@Controller
public class MemberController {
@RequestMapping("/f1")
public String f1() {
System.out.println("执行目标f1方法");
return "success";
}
}
然后配置拦截器要对哪些请求进行拦截
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<ref bean="myInterceptor01"/>
</mvc:interceptor>
</mvc:interceptors>
上面配置的是会对所有请求进行拦截(**表示多级目录),下面访问对应handler查看输出
我们将preHandle方法返回值改为false
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("调用preHandle方法");
//返回false不会执行目标方法
return false;
}
再次请求
多个拦截器执行顺序
在前面的基础上,再创建一个拦截器
@Component
public class MyInterceptor02 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("调用preHandle--02方法");
//返回false不会执行目标方法
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("调用postHandle--02方法");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("调用afterCompletion--02方法");
}
}
配置拦截器
<mvc:interceptor>
<mvc:mapping path="/**"/>
<ref bean="myInterceptor02"/>
</mvc:interceptor>
现在2个拦截器的preHandl都是返回true,放行的,下面查看输出
可以知道执行顺序是 A(pre)->B(pre)->目标方法->B(post)->A(post)->B(after)->A(after)的顺序执行的。
我们方法为什么是过滤器01先执行呢,其实这个顺序就是和spring配置顺序一样的,我在配置文件中先配置的过滤器01,下面交换一下顺序
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<ref bean="myInterceptor02"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<ref bean="myInterceptor01"/>
</mvc:interceptor>
</mvc:interceptors>
再次请求,输出如下,还是符合A(pre)->B(pre)->目标方法->B(post)->A(post)->B(after)->A(after)
将顺序换回来,然后将第一个拦截器的和第二个拦截器的preHandle方法分别返回false,输出如下
可以发现,只要preHandle执行后返回为true,那么afterCompletion就会执行
总结
拦截器可以对请求的一些消息进行过滤,也可以在视图渲染之后执行一些释放的操作,拦截器可以说是和过滤器十分的相似。