SpringMVC 拦截器使用方法 SpringMVC Interceptor拦截器执行顺序理解

一、拦截器作用

        1、Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

二、使用方法

        1、依赖 spring-webmvc

<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-webmvc</artifactId>
	    <version>4.3.20.RELEASE</version>
     </dependency>

        2、创建一个LogInterceptor 类,

                实现 org.springframework.web.servlet.HandlerInterceptor 接口

        3、重写的 preHandle 、 postHandle 、 afterCompletion 作用如下:

/**
	 * preHandle: Controller 执行之前,调用该方法
	 * 返回 true,表示继续执行 ; 返回 false ,终止执行。
	 * 应用: 登陆校验、权限拦截 等。
	 */
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("LogInterceptor =====> preHandle ");
		return true;
	}
	
	/**
	 * postHandle: Controller 执行之后,但未返回视图前,调用此方法。
	 * 应用:对模型数据进行加工处理,加入公用信息以便页面显示 ; 或者手机、平板等移动端访问,返回对应页面数据。
	 */
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView view)
			throws Exception {
		System.out.println("LogInterceptor =====> postHandle ");
		if(null != view) {
			System.out.println("viewName: "+view.getViewName());
		}
		
	}
	
	/**
	 * afterCompletion: Controller 执行之后,且返回视图后,调用此方法。
	 * 应用:日志记录、异常记录、资源清理等。
	 */
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("LogInterceptor =====> afterCompletion ");
	}

        4、spirng-mvc.xml 中配置拦截器

<mvc:interceptors>
    <!-- LogInterceptor  -->
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean id="logInterceptor" class="com.runcode.interceptor.LogInterceptor" />
    </mvc:interceptor>
  </mvc:interceptors>

        5、启动项目,请求任意一个url,可以看到控台输出:

LogInterceptor =====> preHandle  //  执行Controller 之前
hello  // 执行Controller
LogInterceptor =====> postHandle // 执行Controller,返回视图之前 
LogInterceptor =====> afterCompletion // 执行Controller,返回视图之后

三、执行顺序理解

        1、分别创建 FirstInterceptor 和 SecondInterceptor 

public class FirstInterceptor implements HandlerInterceptor {
	
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("FirstInterceptor  ---> preHandle" );
		return true;
	}
	
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("FirstInterceptor  ---> postHandle" );
	}
	
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("FirstInterceptor  ---> afterCompletion" );
	}
}

        2、FirstInterceptor 和 SecondInterceptor 顺序 配置如下(先First,后Second):

<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/userController/**"/>
			<bean class="com.runcode.interceptor.FirstInterceptor" />
		</mvc:interceptor>
		<mvc:interceptor>
			<mvc:mapping path="/userController/**"/>
			<bean class="com.runcode.interceptor.SecondInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>

        3、FirstInterceptor 和 SecondInterceptor 的 preHandle 方法都返回 true

        4、控制台输出如下:

FirstInterceptor  ---> preHandle
SecondInterceptor  ---> preHandle
SecondInterceptor  ---> postHandle
FirstInterceptor  ---> postHandle
SecondInterceptor  ---> afterCompletion
FirstInterceptor  ---> afterCompletion

        5、SecondInterceptor 和 FirstInterceptor 倒序 配置如下(先Second,后First)

<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/userController/**"/>
			<bean class="com.runcode.interceptor.SecondInterceptor" />
		</mvc:interceptor>
		<mvc:interceptor>
			<mvc:mapping path="/userController/**"/>
			<bean class="com.runcode.interceptor.FirstInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>

        6、FirstInterceptor 和 SecondInterceptor 的 preHandle 方法都返回 true 。

        7、控制台输出如下:

SecondInterceptor  ---> preHandle
FirstInterceptor  ---> preHandle
FirstInterceptor  ---> postHandle
SecondInterceptor  ---> postHandle
FirstInterceptor  ---> afterCompletion
SecondInterceptor  ---> afterCompletion

        8、根据拦截器配置顺序:

        配置在前: preHandle 先执行; postHandle 和 afterCompletion,后执行。

四、返回false时测试

        1、FirstInterceptor 和 SecondInterceptor 顺序配置,但FirstInterceptor 的 preHandle返回 false , SecondInterceptor 的preHandle返回 true 。 (先First,后Second , 配置 【三-2】)

        2、控制台输出如下:

FirstInterceptor ---> preHandle

        3、结论: SecondInterceptor 和 Controller 都不执行。

        4、FirstInterceptor 和 SecondInterceptor 顺序配置,但FirstInterceptor的preHandle返回 true , SecondInterceptor 的preHandle返回 false 。(先First,后Second , 配置 【三-2】)

FirstInterceptor  ---> preHandle
SecondInterceptor  ---> preHandle
FirstInterceptor  ---> afterCompletion

        5、结论:拦截器中只要有返回false,则 postHandle 方法不会执行 ; 单一拦截器中,preHandle 返回true, afterCompletion 才会执行。

五、总结

        1、按照 springmvc.xml中配置的拦截器先后顺序,规律如下:

  • preHandle 按照顺序执行 (配置在前,先执行)
  • postHandle 按照倒序执行。 (配置在前,后执行)
  • afterCompletion 同 postHandle 。

        2、多个拦截器中,只要有返回false,则 postHandle 方法不会执行。(全部返回true,postHandle 方法才执行)

        3、多个拦截器中,只要有返回 false,则对应 Controller 也不会执行。

        4、单一拦截器中,preHandle 返回true,则 afterCompletion 才会执行。

        5、单一拦截器中,preHandle 返回 false,则 preHandle 和 afterCompletion 不会执行。