Spring MVC也可以使用拦截器对请求进行拦截处理,用户 可以自定义拦截器来实现特定的功能,自定义的拦截器必 须实现HandlerInterceptor接口。
preHandle():这个方法在业务处理器处理请求之前被调用,在该 方法中对用户请求 request 进行处理。如果程序员决定该拦截器对 请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去 进行处理,则返回true;如果程序员决定不需要再调用其他的组件 去处理请求,则返回false。
postHandle():这个方法在业务处理器处理完请求后,但是DispatcherServlet 向客户端返回响应前被调用,在该方法中对 用户请求request进行处理。
afterCompletion():这个方法在 DispatcherServlet 完全处理完请 求后被调用,可以在该方法中进行一些资源清理的操作。
自定义拦截器大白话:
1、首先新建一个拦截器类
就是 implements HandlerInterceptor 实现接口类就行。
public class FirstIntercept implements HandlerInterceptor{
/**
* 该方法在目标方法之前被调用.
* 若返回值为 true, 则继续调用后续的拦截器和目标方法.
* 若返回值为 false, 则不会再调用后续的拦截器和目标方法.
*
* 可以考虑做权限. 日志, 事务等.
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
System.out.println("[FirstIntercept] preHandle");
return true;
}
/**
* 调用目标方法之后, 但渲染视图之前.
* 可以对请求域中的属性或视图做出修改.
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.println("[FirstIntercept] postHandle");
}
/**
* 渲染视图之后被调用. 释放资源
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
System.out.println("[FirstIntercept] afterCompletion");
}
}
2、编辑转发配置文件
<mvc:interceptors>
<!-- 配置自定义拦截器 -->
<bean class="com.test.springmvc.test.FirstIntercept"></bean>
<!-- 配置 带参数的 自定义拦截器,SencondIntercept和FirstIntercept 代码一样的只是改了名字,这里就不写了 -->
<mvc:interceptor>
<!-- 拦截器只作用在 /emps 请求域中,一定要记得“/”,否则没有效果 -->
<mvc:mapping path="/emps"/>
<bean class="com.test.springmvc.test.SecondIntercept"></bean>
</mvc:interceptor>
</mvc:interceptors>
3、拦截器执行顺序:
(1)如果只配置了FirstIntercept,且里面的 preHandle方法返回true,且没有 配置 带参数的 自定义拦截器(即SencondIntercept)
那么url请求,控制台输出结果:
[FirstIntercept] preHandle [FirstIntercept] postHandle [FirstIntercept] afterCompletion
(2)如果上面的FirstIntercept里面的preHandle方法返回false。且没有 配置 带参数的 自定义拦截器(即SencondIntercept)
那么url请求,控制台输出结果:
[FirstIntercept] preHandle
(3)如果配置了FirstIntercept 和SecondIntercept,且两者里面的preHandle方法都返回true,且请求域是emps
控制台输出结果:
[FirstIntercept] preHandle [SecondIntercept] preHandle [SecondIntercept] postHandle [FirstIntercept] postHandle [SecondIntercept] afterCompletion [FirstIntercept] afterCompletion
(4)如果配置了FirstIntercept 和SecondIntercept请求域是emps
而FirstIntercept的preHandle方法返回true,SecondIntercept的preHandle方法返回false,控制台输出结果:
[FirstIntercept] preHandle [SecondIntercept] preHandle [FirstIntercept] afterCompletion
备注:下图中的虚线不是执行过程,实线才是真正的执行过程。
特别提醒:当初在改项目代码时,因为代码是热更新的,但是测试结果来看,热更新后,Intercept 的测试输出 有bug ,因为多输出了 一遍 下面的:
[FirstIntercept] preHandle
[FirstIntercept] postHandle
[FirstIntercept] afterCompletion
所以,测试代码时最好还是重启一下服务器,这样就不会出现意想不到的bug。
4、拦截器顺序与异常
当自定义拦截器的preHandle方法返回true,遇到springmvc出现异常时:
1、DefaultHandlerExceptionResolver 系统默认自带异常处理器。
里面实现了很多异常 ,如:handleHttpRequestMethodNotSupported
我测试控制器规定了请求方法只能是post,当我get请求时,出异常了。
@RequestMapping(value="/testDefaultHandlerExceptionResolver",method=RequestMethod.POST)
public String testDefaultHandlerExceptionResolver(){
System.out.println("testDefaultHandlerExceptionResolver...");
return "success";
}
控制台打印的是:(看出来,自定义拦截器根本没有调用到)
org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported WARNING: Request method 'GET' not supported
网页显示:
HTTP Status 405 - Request method 'GET' not supported type Status report message Request method 'GET' not supported description The specified HTTP method is not allowed for the requested resource. Apache Tomcat/8.0.36
2、其他 遇到下面的异常捕获器:
@ResponseStatus (优先级第一)
@ExceptionHandler,@ControllerAdvice(优先级第二)
SimpleMappingExceptionResolver (优先级第三)
控制台结果显示:(自定义拦截器调用了方法一和方法三)
[FirstIntercept] preHandle [FirstIntercept] afterCompletion


