SpringMVC 拦截器


SpringMVC 拦截器的原理图

SpringMVC拦截器的实现一般有两种方式

     第一种方式是自定义的Interceptor类要实现Spring的 HandlerInterceptor 接口

     第二种方式是继承实现了HandlerInterceptor接口的类,比如Spring已经提供的实现了HandlerInterceptor接口的抽象类HandlerInterceptorAdapter

HandlerInterceptor 接口中定义了三个抽象方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。

     preHandle(): 这个方法在业务处理器处理请求之前被调用,SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

     postHandle():这个方法在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行。

     afterCompletion():该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。

下面来看我们的Interceptor类

 1 import javax.servlet.http.HttpServletRequest;
 2 import javax.servlet.http.HttpServletResponse;
 3 
 4 import org.slf4j.Logger;
 5 import org.slf4j.LoggerFactory;
 6 import org.springframework.web.servlet.ModelAndView;
 7 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 8 
 9 public class CommonInterceptor  extends HandlerInterceptorAdapter{
10 
11         private final Logger log = LoggerFactory.getLogger(CommonInterceptor.class);
12 
13         public  static  final  String  LAST_PAGE = "lastPage";
14         /** 
15          * 在业务处理器处理请求之前被调用 
16          * 如果返回false 
17          *     从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
18          *     
19          * 如果返回true 
20          *    执行下一个拦截器的preHandle(),直到所有的拦截器都执行完毕 
21          *    再执行被拦截的Controller 
22          *    然后进入拦截器链, 
23          *    从最后一个拦截器往回执行所有的postHandle() 
24          *    接着再从最后一个拦截器往回执行所有的afterCompletion() 
25          */  
26         @Override  
27         public boolean preHandle(HttpServletRequest request,  
28                 HttpServletResponse response, Object handler) throws Exception {            
29             if ("GET".equalsIgnoreCase(request.getMethod())) {
30                     RequestUtil.saveRequest();
31             }
32             log.info("==============执行顺序: 1、preHandle================");  
33             String requestUri = request.getRequestURI();
34             String contextPath = request.getContextPath();
35             String url = requestUri.substring(contextPath.length());         if ("/userController/login".equals(url)) {                  
36                     return true;
37             }else {               
38                     String username =  (String)request.getSession().getAttribute("user"); 
39                     if(username == null){
40                             log.info("Interceptor:跳转到login页面!");
41                             request.getRequestDispatcher("/page/index.jsp").forward(request, response);
42                             return false;
43                     }else
44                             return true;   
45            }
46             
47         }        
48         /**
49          * 在业务处理器处理请求执行完成后,生成视图之前执行的动作   
50          * 可在modelAndView中加入数据,比如当前时间
51          */
52         @Override  
53         public void postHandle(HttpServletRequest request,  
54                 HttpServletResponse response, Object handler,  
55                 ModelAndView modelAndView) throws Exception {   
56             log.info("==============执行顺序: 2、postHandle================");  
57             if(modelAndView != null){  //加入当前时间  
58                 modelAndView.addObject("haha", "测试postHandle");  
59             }  
60         }        
61         /** 
62          * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等    
63          * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion() 
64          */  
65         @Override  
66         public void afterCompletion(HttpServletRequest request,  
67                 HttpServletResponse response, Object handler, Exception ex)  
68                 throws Exception {  
69             log.info("==============执行顺序: 3、afterCompletion================");  
70         }  
71 }

spring-MVC.xml的相关配置

 1 
 2     <mvc:interceptors> 
 3            <mvc:interceptor>
 4                     
 9                    <mvc:mapping path="/**" /> 
10                      
11                    
12                    <bean id="commonInterceptor" class="org.shop.interceptor.CommonInterceptor">bean> 
13           mvc:interceptor> 
14           
15     mvc:interceptors>

 

springboot设置拦截器的方法

步骤1.编写一个方法实现HandlerInterceptor接口。

 1 public class MyInterceptors implements HandlerInterceptor {
 2 @Override
 3 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
 4 throws Exception {
 5 System.out.println("运行时执行。。。。。。。。。。。。。");
 6 return true;
 7 }
 8 
 9 @Override
10 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
11 ModelAndView modelAndView) throws Exception {
12 
13 }
14 
15 @Override
16 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
17 throws Exception {
18 
19 }
20 }

步骤2.开启拦截器的配置路径,再写一个类,这个类要加上@Configuration,继承 WebMvcConfigurerAdapter 父类,重写 addInterceptors 方法。

@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
//对所有的进行拦截 放行登录页面和首页
registry.addInterceptor(new MyInterceptors2()).addPathPatterns("/**").excludePathPatterns("/user/login","index.html");
}