前言
在学习SSM的时候遇到了拦截器问题,Spring MVC的处理器拦截器类似于Servlet 开发中的过滤器Filter,本文主要总结一下Spring MVC中拦截器是如何定义的,以及测试拦截器的执行情况和使用方法。供大家参考
拦截器(Interceptor)
拦截器的前世今生
在HandlerInterceptor接口中,定义了 3 个方法,分别为preHandle()、postHandle()和afterCompletion(),我们就是通过复写这 3 个方法来对用户的请求进行拦截处理的。因此,我们可以通过直接实现HandlerInterceptor接口来实现拦截器的功能。不过在 Spring 框架之中,其还提供了另外一个接口和一个抽象类,实现了对HandlerInterceptor接口的功能扩展,分别为:AsyncHandlerInterceptor和HandlerInterceptorAdapter.
对于AsyncHandlerInterceptor接口,其在继承HandlerInterceptor接口的同时,又声明了一个新的方法afterConcurrentHandlingStarted();而HandlerInterceptorAdapter抽象类,则是更进一步,在其继承AsyncHandlerInterceptor接口的同时,又复写了preHandle方法。因此,AsyncHandlerInterceptor更像是一个过渡的接口。
在实际应用中,我们一般都是通过实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter抽象类,复写preHandle()、postHandle()和afterCompletion()这 3 个方法来对用户的请求进行拦截处理的。
什么是拦截器
- Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。要使用Spring MVC中的拦截器,就需要对拦截器类进行定义和配置。通常拦截器类可以通过两种方式来定义:
通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义。
通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义。
首先讲解实现HandlerInterceptor接口定义拦截器
/**
* 定义拦截器,实现 HandlerInterceptor 接口,实现接口的三个方法
*/
public class SysInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
//false表示拦截,不向下执行;true表示放行
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
详解三个方法:
- preHandle方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;可以用于身份认证、身份授权。比如如果认证没有通过表示用户没有登陆,需要此方法拦截不再往下执行(return false),否则就放行(return true)。
- postHandle方法:该方法会在控制器方法调用之后,且解析视图之前执行。可以看到该方法中有个modelAndView的形参。应用场景:从modelAndView出发:将公用的模型数据(比如菜单导航之类的)在这里传到视图,也可以在这里同一指定视图。
- afterCompletion方法:该方法会在整个请求完成,即视图渲染结束之后执行。应用场景:统一异常处理,统一日志处理等。
拦截器的xml配置
<!--拦截器-->
<mvc:interceptors>
<!--可以配置多个拦截器-->
<mvc:interceptor>
<!--配置拦截器的作用路径-->
<mvc:mapping path="/*/sys/*"/>
<!--定义在<mvc:interceptor>下面的表示匹配指定路径的请求才进行拦截-->
<bean class="cn.smbms.inteceptor.AdminInteceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
上面的代码中,
<mvc:interceptors>元素用于 配置一组拦截器 ,基子元素<bean>中定义的是全局拦截器,它会拦截所有的请求;而<mvc:interceptor>元素中定义的是指定路径的拦截器,它会对指定路径下的请求生效。<mvc:interceptor>元素的子元素<mvc:mapping>用于配置拦截器作用的路径,该路径在其属性path 中定义。如上述代码中 path 的属性值“/**” 表示拦截所有路径,“/hello” 表示拦截所有以 “/hello” 结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过<mvc:exclude-mapping>元素进行配置。
注意:<mvc:interceptor>中的子元素必须按照上述代码中的配置顺序进行编写,即<mvc:mapping> <mvc:exclude-mapping> <bean>,否则文件会报错。
执行流程
程序先执行preHandle()方法,如果该方法的返回值为true,则程序会继续向下执行处理器中的方法,否则将不再向下执行。
在业务处理器(即控制器Controller类)处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向客户端返回响应。
在DispatcherServlet处理完请求后,才会执行afterCompletion()方法。
继承抽象类 HandlerInterceptorAdapter
里面的方法根据自己的需求实现即可。
public class SysInterceptor1 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("WrongCodeInterceptor, preHandle......");
return true;
}
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
System.out.println("WrongCodeInterceptor, postHandle......");
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("WrongCodeInterceptor, afterCompletion......");
}
@Override
public void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("WrongCodeInterceptor, afterConcurrentHandlingStarted......");
}
}
总结
本篇博文带大家了解Spring MVC拦截器的流程,常用的接口和抽象类。