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");

}