前言

拦截器是Spring MVC中强大的控件,它可以在处理器之前做一些操作,或者是在处理器完成后做一个操作,甚至是在渲染视图,也就是viewResolver之后做一些操作。我们知道,在web.xml网站描述文件中,我们会配置DispatchServlet,然后SpringMVC启动的时候就回通过@requestMapping的注解解析统一资源定位符URI和处理器handler之间的关系,在运行的时候,通过URL请求找到对应的HandlerMapping,然后构建HandlerExecuteChain对象,再交给handleradapter执行。

HandlerInterceptor

一般要实现拦截器,需要实现HandlerInterceptor接口,这个接口有三个方法,如下:

public interface HandlerInterceptor {


	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return true;
	}

	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}


	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
	}

}


以上三个方法意义:

1、preHandler():在处理器之前执行的前置方法,这样SpringMVC可以在进入到处理器之前进行一些处理,需要注意的是,这里返回的是一个Boolean,这会影响到后面的SpringMVC的执行。
2、postHandler():在处理器执行之后执行的后置方法,处理器handler执行完毕会调用它。
3、afterCompletion():无论是否产生异常,都会在渲染视图之后执行。



这里需要注意的是,当preHandler返回false后,就不会执行postHandler和afterCompletion方法。

拦截器实现

拦截器需要实现HandlerInterceptor接口,在SpringMVC中,可以通过一个虚类拦截器来实现。

public class MyInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        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");

    }
}

此外,还需要在SpringMVC的配置文件中设置:

    <mvc:interceptors>
        <mvc:interceptor>
            <!--配置拦截器拦截的路径-->
            <mvc:mapping path="/*.do"/>
            <!--配置拦截器-->
            <bean class="com.dimple.interceptor.RoleInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

多个拦截器

这里限于篇幅,只是随便说一下多个拦截器执行的顺序,当配置了多个拦截器后,执行的顺序和责任链的执行顺序一样。
按照配置文件配置:
如果在配置文件中按照顺序配置拦截器1、拦截器2、拦截器3

在正常情况下,Spring会从第一个拦截器进入到前置方法,这样前置方法是按照配置顺序执行的,然后再运行处理器的代码,最后再运行后置方法。**注意这里的后置方法和前置方法是逆序的,和责任链的运行顺序是一样的。**

如下的结果:

preHandler1
preHandler2
preHandler3
···
/**控制器执行的方法*/
···
postHandler3
postHandler2
postHandler1
···
afterCompletion3
afterCompletion2
afterCompletion1

但是如果前置方法返回false,那么后面的prehandler方法也不会执行了,而控制器和所有的postHandler也不会执行。执行过preHandler方法且方法返回为true的拦截器的完成方法afterCompletion会按照配置顺序的逆序执行。