SpringMVC 配置拦截器
1. 作为拦截器当然是为了拦截 (这不是废话嘛) 那拦截是为了干嘛?
它可以帮我们拦截未登录用户 验证是否登录、设置日志记录、统计一些接口访问量啊
进行统一异常处理 设置一些数据啊 或者计算下应用接口方法执行效率啊 等等
2. 配置拦截器
由于用的是SpringMVC所以要知道 它是有个统一的 DispatcherServlet 控制器,
所以就不用传统的bean方式了,人家给我们提供了其他简单的方式
如下所示: (我设置了三个方便测试用的)
<!--拦截器 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<!-- 表示拦截所有的url,包括子url路径 -->
<bean class="com.tz.interceptor.LoginHandlerInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.tz.interceptor.LoginHandlerInterceptor2"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.tz.interceptor.LoginHandlerInterceptor3"></bean>
</mvc:interceptor>
</mvc:interceptors>
SpringMVC 拦截器需要实现 HandlerInterceptor 接口,它有三个方法:
(1) preHandle方法
该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的,
可以同时存在,多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的
执行,而且所有的Interceptor中的preHandle方法都会在 Controller方法调用之前调用。
SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令 preHandle的返回值为false,当preHandle的返回值为false的时候整个请求就结束了。
(2) postHandle 方法
这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。
postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之后,
也就是在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的
渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操作,
这个方法的链式结构跟正常访问的方向是相反的,
也就是说先声明的Interceptor拦截器该方法反而会后调用,(这句话等下你就会明白了)
这跟Struts2里面的拦截器的执行过程有点像,
只是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法
Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor
或者是调用action,然后要在Interceptor之前调用的内容都写在调用invoke之前,
要在Interceptor之后调用的内容都写在调用invoke方法之后
(3) afterCompletion方法
请求完成后调用,这时把你要做什么事写上去,比如 清理资源
那么建立的拦截器类: 其他两个都一样
public class LoginHandlerInterceptor implements HandlerInterceptor {
/***
* 请求传送到接口之前调用该方法,如true通过则进入接口请求数据
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("LoginHandlerInterceptor ------ preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {
System.out.println("LoginHandlerInterceptor ------ postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("LoginHandlerInterceptor ------ afterCompletion");
}
}
3.那么多个拦截器的执行过程又是如何的?
第二个拦截器不通过的 结果:
LoginHandlerInterceptor ----------preHandle
LoginHandlerInterceptor2 ------ preHandle
LoginHandlerInterceptor ----------afterCompletion
也就是说第二个拦截器不会执行他自己之后的两个方法和postHandle() 方法 ,以及之后的拦截器
第三个拦截器不通过的 结果:
LoginHandlerInterceptor ----------preHandle
LoginHandlerInterceptor2 ------ preHandle
LoginHandlerInterceptor3 ------------ preHandle
LoginHandlerInterceptor2 ------ afterCompletion
LoginHandlerInterceptor ----------afterCompletion
也就是说第三个拦截器不会执行他自己之后的两个方法和postHandle() 方法 ,以及之后的拦截器
当3个拦截器都通过执行时:
LoginHandlerInterceptor ----------preHandle
LoginHandlerInterceptor2 ------ preHandle
LoginHandlerInterceptor3 ------------ preHandle
LoginHandlerInterceptor3 ---------- postHandle
LoginHandlerInterceptor2 ------ postHandle
LoginHandlerInterceptor ---------- postHandle
LoginHandlerInterceptor3 ---------- afterCompletion
LoginHandlerInterceptor2 ------ afterCompletion
LoginHandlerInterceptor ---------- afterCompletion
总结下:
所以是执行通过了所有的PreHandle()方法之后 才会执行 postHandle() 方法;
preHandle() 方法如果通过了 则执行下一个preHandle(), 不通过则不执行;
然后执行 通过 preHandle() 方法的拦截器的 afterCompletion() 方法
我随性写了个登录拦截器 大神勿喷
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//获取请求的url
String url = request.getRequestURI();
System.out.println("LoginHandlerInterceptor ----------preHandle");
//判断url是否是公开地址,实际使用时应该将公开地址配置在配置文件中,这里公开地址是登录提交的地址
if(url.indexOf("login") >= 0){
//如果是登录提交,则放行
return true;
}
HttpSession session = request.getSession();
//从session中取出用于身份信息
String username = (String) session.getAttribute("tzUserName");
if(username != null){
//身份信息验证通过,放行
return true;
}
//没有校验通过,表示用户身份需要认证,此时需要跳转到登录页面
request.getRequestDispatcher("/views/login.jsp").forward(request, response);
//返回false表示拦截,不向下执行
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("LoginHandlerInterceptor ----------postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("LoginHandlerInterceptor ----------afterCompletion");
}