一、简介
SpringMVC的处理器拦截类似于servlet开发中的过滤器Filter,用于对请求进行拦截处理。拦截器是基于SpringAOP实现的,它是AOP编程思想的典型应用。
二、常见应用场景
- 权限检验:检测请求是否具有登录权限,如果没有直接返回登录页面。
- 性能监控:用请求处理前和请求处理后的时间差计算整个请求相应完成所消耗的时间。
- 日志记录:记录请求信息的日志,以便进行信息监控、信息统计等。
三、使用方法
SpringMVC实现拦截的功能,主要有两个途径,第一种实现是实现HandleIntercepter接口(在Spring框架中,还提供了另外一个接口和抽象类实现了对HandleIntercepter接口的功能拓展,分别为:AsyncHandlerInterceptor和 HandlerInterceptorAdapter) ,第二种是实现WebRequestIntercepter接口。
A,HandlerIntercepter接口详解:
在接口中定义了3个方法,分别为:preHandle(),postHandle和afterCompletion(),通过复写这3个方法可以实现用户的请求进行拦截处理。AsyncHandlerInterceptor接口,其在继承HandlerInterceptor接口的同时,又声明了一个新的方法afterConcurrentHandlingStarted();而HandlerInterceptorAdapter抽象类,则是更进一步,在其继承AsyncHandlerInterceptor接口的同时,又复写了preHandle方法。因此,AsyncHandlerInterceptor更像是一个过渡的接口。
在实际应用中,咱们一般都是通过实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter抽象类,复写preHandle()、postHandle()和afterCompletion()这 3 个方法来对用户的请求进行拦截处理的。
B,WebRequestIntercetor
在WebRequestInterceptor接口中也定义了 3 个方法,同HandlerInterceptor接口完全相同,咱们也是通过复写这 3 个方法来用户的请求进行拦截处理的。而且这 3 个方法都传递了同一个参数 WebRequest,那么这个 WebRequest 到底是什么呢?其实这个 WebRequest 是 Spring 中定义的一个接口,它里面的方法定义跟 HttpServletRequest 类似,在WebRequestInterceptor中对 WebRequest 进行的所有操作都将同步到 HttpServletRequest 中,然后在当前请求中依次传递。
在 Spring 框架之中,还提供了一个和WebRequestInterceptor接口长的很像的抽象类,那就是:WebRequestInterceptorAdapter,其实现了AsyncHandlerInterceptor接口,并在内部调用了WebRequestInterceptor接口。
C,配置拦截器
拦截器是基于SpringAOP来实现的。对于AOP不熟悉的朋友,需要先了解下几个概念:
- Join Point,表示“连接点”,它是程序运行中的某个阶段点,比如方法的调用、异常的抛出等;
- Advice,表示“通知”,它是某个连接点所采用的处理逻辑,也就是向连接点注入的代码;
- Pointcut,表示“切入点”,它是“连接点”的集合,是程序中需要注入 Advice 的位置的集合,指明 Advice 要在什么样的条件下才能被触发
- Advisor,它是 Pointcut 和 Advice 的配置器,包括 Pointcut 和 Advice,是将 Advice 注入程序中 Pointcut 位置的代码。
接下来,给出 XML 配置文件的声明:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
在 XML 文件的头部声明完之后,咱们就可以在 Spring 的配置文件中就可以使用mvc
标签啦!而在mvc
标签中有一个名为mvc:interceptors
的标签,该标签就是用于声明 Spring 拦截器的。在mvc:interceptors标签下声明interceptor标签主要有两种方式:
- 直接定义一个 Interceptor 实现类的 bean 对象,使用这种方式声明的 Interceptor 拦截器将会对所有的请求进行拦截;
- 使用
mvc:interceptor
标签进行声明,使用这种方式进行声明的 Interceptor 可以通过mvc:mapping
子标签来定义需要进行拦截的请求路径。
下面,给出一个配置示例:
<mvc:interceptors>
<!-- 使用 bean 定义一个 Interceptor,直接定义在 mvc:interceptors 下面的 Interceptor 将拦截所有的请求 -->
<bean class="com.hit.interceptor.WrongCodeInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/demo/hello.do"/>
<!-- 定义在 mvc:interceptor 下面的 Interceptor,表示对特定的请求进行拦截 -->
<bean class="com.hit.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
在<mvc:interceptors>中可以同时配置多个拦截器,形成拦截器链或拦截器栈。而这些拦截器的执行顺序是按声明的先后顺序执行的,即:先声明的拦截器先执行,后声明的拦截器后执行。
D,简单应用举例
下面是一个简单的HandlerInterceptor拦截器配置和应用的例子。
1,配置文件
<mvc:interceptors>
<!--对所有的请求进行拦截-->
<!--<beans:beanclass="com.sunp.common.interceptor.Myinterceptor"/>-->
<!--对特定的请求进行拦截-->
<mvc:interceptor>
<!--进行拦截的路径-->
<mvc:mapping path="/**"/>
<!--不进行拦截的路径-->
<mvc:exclude-mapping path="/lib/**" />
<beans:bean class="com.sunp.common.interceptor.Myinterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
2,实现接口并继承方法
public class myInterceptor implements HandlerInterceptor{
@Override
public boolean preHandler(HttpServletRequest request, HttpServletResponse response, Object obj)throws Exception{
/*该方法将在请求处理之前进行调用,只有该方法返回true,才会继续执行后续的Interceptor和Controller,当返回值为true 时就会继续调用下一个Interceptor的preHandle 方法,如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller方法;*/
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object obj,Exception e)throws Exception {
/*该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用,可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。*/
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,Object arg2,ModelAndView arg3) throws Exception {
/*该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。用于进行资源清理。*/
}
}
四、执行顺序
1,单个实现类的执行顺序
preHandler -> Controller -> postHandler -> model渲染-> afterCompletion
2,多个实现类的执行顺序
———————preHandler1——————-
———————preHandler2——————-
———————preHandler3——————-
———————–Controller———————
———————postHandler3——————
———————postHandler2——————
———————postHandler1——————
———————postHandler1——————
——————afterCompletion3—————-
——————afterCompletion2—————-
——————afterCompletion1—————-
参考连接:https://blog.csdn.net/qq_35246620/article/details/68487904