[toc]

SpringMVC之拦截器

1. 拦截器概述

  • 注意拦截器和过滤器的区别:过滤器先执行,可以理解为拦截器是过滤器的升级版。

  • SpringMVC有很多默认的拦截器我们使用SpringMVC的时候就使用了,如果我们想自定义拦截器可以通过下面方式实现。

  • 自定义拦截器:SpringMVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器可以实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter 适配器类

  • ~~~~java
    public interface HandlerInterceptor {

    // 在目标方法运行之前调用,返回boolean,return true 放行,return false;不放行。
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception;
    // 在目标方法运行之后调用。
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;
    
    // 在请求整个完成之后,即资源响应之后。
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;
    

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54

    #### 2. 自定义拦截器流程

    1. 搭建SpringMVC的环境,`配置springMVC.xml和web.xml`。

    2. web.xml配置

    ~~~~~xml
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <!--前端控制器-->
    <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springMVC.xml</param-value>
    </init-param>
    </servlet>

    <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!--只不匹配jsp-->
    <url-pattern>/</url-pattern>
    </servlet-mapping>

    </web-app>
    ~~~~~

    3. 在`springMVC.xml`中拦截器配置:

    ~~~~xml
    <context:component-scan base-package="cn.justweb"/>

    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"></property>
    <property name="suffix" value=".jsp"></property>
    </bean>

    <!--注解驱动,自动注入mvc里面的组件-->
    <mvc:annotation-driven/>

    <!--自定义拦截器的配置-->

    <!--先配谁先执行谁-->
    <mvc:interceptors>
    <bean class="cn.justweb.interceptor.FirstInterceptor"></bean>
    <bean class="cn.justweb.interceptor.SecInterceptor"/>
    </mvc:interceptors>

  1. 定义一个拦截器FirstInterceptor,实现HandlerInterceptor接口,并重写其中的三个方法。

  2. 第一个拦截器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    //配置的第一个拦截器
    public class FirstInterceptor implements HandlerInterceptor {
    /**
    * 执行流程:
    * 拦截器的preHandle方法执行了
    * controller中的testInterceptor方法
    * 拦截器postHandle方法执行了
    * 拦截器的afterCompletion执行了
    * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("拦截器的preHandle方法执行了");
    //此处为true的时候才执行下面的事情
    return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    System.out.println("拦截器postHandle方法执行了");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    System.out.println("拦截器的afterCompletion执行了");
    }
    }
  3. 第二个拦截器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    //配置的第二个拦截器
    public class SecInterceptor implements HandlerInterceptor {
    /**
    * 执行流程:
    * 拦截器的preHandle方法执行了
    * 拦截器2的preHandle方法执行了
    * controller中的testInterceptor方法
    * 拦截器2的postHandle方法执行了
    * 拦截器postHandle方法执行了
    * 拦截器2的afterCompletion方法执行了
    * 拦截器的afterCompletion执行了
    * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("拦截器2的preHandle方法执行了");
    return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    System.out.println("拦截器2的postHandle方法执行了");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    System.out.println("拦截器2的afterCompletion方法执行了");

    }
    }
  4. 测试

    1
    2
    3
    4
    5
    6
    7
    8
    @Controller
    public class SpringMVCHandler {
    @RequestMapping("/testInterceptor")//拦截器
    public String testInterceptor(){
    System.out.println("controller中的testInterceptor方法");
    return "success";
    }
    }

3. 拦截器小结

3.1 自定义拦截器
  •  `1. 实现接口: HandlerInterceptor`
    
  •  `2. 继承 HandlerInterceptorAdaptor`
    
3.2 单个拦截器中的三个方法
  •  `preHandle:在调用处理方法之前执行  dispatcherServlet类中939行`
    
  •  `postHandle:在调用处理方法之后执行  dispatcherServlet类中954行`
    
  • afterCompletion:在mv执行渲染后执行 dispatcherServlet类中1030行
3.3 多个拦截器的执行顺序
  • 1.拦截器的执行顺序由配置的顺序决定,先配置拦截器,然后再运行执行。

  • 2.拦截器方法的执行顺序

    •      /*
           * 执行流程:
           * 拦截器的preHandle方法执行了
           * 拦截器2的preHandle方法执行了
           * controller中的testInterceptor方法
           * 拦截器2的postHandle方法执行了
           * 拦截器postHandle方法执行了
           * 拦截器2的afterCompletion方法执行了
           * 拦截器的afterCompletion执行了
           */
      
  • preHandle:与配置的的顺序一致

  • postHandle:与配置的顺序相反

  • afterCompletion:与配置的顺序相反

4. Filter和拦截器

4.1 什么时候用Filter什么时候用拦截器?

如果某些功能,需要其他组件配合完成,我们就使用拦截器,其他情况可以写Filter。

4.2 拦截器与过滤器的区别

拦截器与过滤器的区别