自定义拦截器
• Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口
– preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求request 进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false。
– postHandle():这个方法在业务处理器处理完请求后,但–是DispatcherServlet向客户端返回响应前被调用,在该方法中对用户请求request进行处理。
– afterCompletion():这个方法在DispatcherServlet完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
实例测试:
FirstInterceptor.java
package com.xyc.springmvc.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
*
* @ClassName: FirstInterceptor
* @Description:拦截器
* @author: xyc
* @date: 2017年1月4日 下午9:26:59
*
*/
public class FirstInterceptor implements HandlerInterceptor {
/**
*
* <p>Title: preHandle</p>
* <p>Description: </p>
* 该方法在目标方法之前被调用.若返回值为 true, 则继续调用后续的拦截器和目标方法. 若返回值为 false, 则不会再调用后续的拦截器和目标方法.
* 可以考虑做权限. 日志, 事务等.
* @param request
* @param response
* @param handler
* @return
* @throws Exception
* @see org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("[FirstInterceptor] preHandle");
return true;
}
/**
*
* <p>Title: postHandle</p>
* <p>Description: </p>
* 调用目标方法之后, 但渲染视图之前.
* 可以对请求域中的属性或视图做出修改. 当出异常的时候,不走这个方法,走下面的后置处理器
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
* @see org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.web.servlet.ModelAndView)
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("[FirstInterceptor] postHandle");
}
/**
*
* <p>Title: afterCompletion</p>
* <p>Description: </p>
* 渲染视图之后被调用. 释放资源
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
* @see org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
System.out.println("[FirstInterceptor] afterCompletion");
}
}
配置:
<!-- 配置拦截器 -->
<mvc:interceptors>
<bean class="com.xyc.springmvc.interceptor.FirstInterceptor"></bean>
</mvc:interceptors>
/**
*
* @Title: testInterceptor
* @Description: 测试拦截器的目标方法
* @param: @return
* @return: String
* @throws
*/
@RequestMapping("/testInterceptor")
public String testInterceptor(){
System.out.println("testInterceptor");
return "success";
}
请求http://localhost:8081/testInterceptor之后,测试结果:
拦截器方法执行的顺序:
配置拦截器
新增SecondInterceptor拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 拦截所有请求 -->
<bean class="com.xyc.springmvc.interceptor.FirstInterceptor"></bean>
<!-- 拦截指定资源 配置拦截器作用的路径-->
<mvc:interceptor>
<mvc:mapping path="/testInterceptor"/>
<bean class="com.xyc.springmvc.interceptor.SecondInterceptor"></bean>
<!-- 配置拦截器不作用的路径 -->
<!-- <mvc:exclude-mapping path=""/> -->
</mvc:interceptor>
</mvc:interceptors>
源码分析:
所以当第一个拦截器返回false时候,结果:
当第第一个拦截器true,第二个拦截器false时,结果:
补:当过滤器、拦截器、切面同时存在的时候,是什么样子的执行顺序呢?
过滤器先执行,拦截器之后执行,遇到异常之后,先被异常处理机制捕获处理,再到切面执行后执行具体的handler, 当然遇到异常的时候最先被切面捕获,之后到异常处理机制
1.过滤器执行链之前(chain.doFilter之前)
2.拦截器前置通知
3.切面(没分前置通知,后置通知,只测试了一个环绕通知)
4.具体的handler
5.拦截器postHandle
6.拦截器后置处理器
7.过滤器chain.doFilter之后
过滤器里面拿不到具体执行的handler名称,方法等, 拦截器里面可以拿到但是拿不到参数, 切面所有的都可以拿到