我的文章-Spring程序员

SpringMVC 拦截器 HandlerInterceptor

2018-05-20  本文已影响18人  飞翔的鲲

HandlerInterceptor 结构


拦截方法一般写在 preHandle()。

public interface HandlerInterceptor {
    boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;

    void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
}

sprng-mvc.xml 拦截器配置


当然要使此配置生效,还需要web.xml配置springMVC请求路径,这里就不多说了。

      <!--拦截器, 对路径进行拦截-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--拦截后台页面的请求-->
            <mvc:mapping path="/back/**"/>
            <!--<mvc:mapping path="/test/testMethod"/>-->
            <!--不拦截登录页和登录的请求-->
            <mvc:exclude-mapping path="/back/loginPage.htm"/>
            <mvc:exclude-mapping path="/back/login.htm"/>
            <bean class="com.ppf.test.inteceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

  1. 拦截器配置说明
如果只设置了   <mvc:mapping path="/**"/>
表明对一切进入SpringMVC的请求拦截。
如果这样设置 <mvc:mapping path="/back/**"/>
SpringMVC 会去映射表中查找对应的controller ,如果查找不到就不拦截。

原理


image.png
  1. DispatcherServlet会调doDispathc()方法 ,mappedHandler = this.getHandler(processedRequest); 获取 一个handler。这个handler怎么来的呢?
  2. 他会调 DispatcherServlet 的 getHandler 方法。这里可以看到 handler 其实就是 HandlerExecutionChain ,这个 handlerExecutionChain 是哪里的呢?
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Iterator var2 = this.handlerMappings.iterator();

        HandlerExecutionChain handler;
        do {
            if (!var2.hasNext()) {
                return null;
            }

            HandlerMapping hm = (HandlerMapping)var2.next();
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
            }

            handler = hm.getHandler(request);
        } while(handler == null);

        return handler;
    }
  1. handlerExecutionChain 其实是HandlerMapping 调用getHandler得到的。
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Object handler = this.getHandlerInternal(request);
        if (handler == null) {
            handler = this.getDefaultHandler();
        }

        if (handler == null) {
            return null;
        } else {
            if (handler instanceof String) {
                String handlerName = (String)handler;
                handler = this.getApplicationContext().getBean(handlerName);
            }

            HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);
            if (CorsUtils.isCorsRequest(request)) {
                CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
                CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
                CorsConfiguration config = globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig;
                executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
            }

            return executionChain;
        }
    }

  1. 这个 getHandlerExecutionChain 具体做了什么呢?
    当然是获取 HandlerExecutionChain,本文重点探讨的拦截器就是在这里加的。
    从中可以看出,配置文件中加的拦截器最后是在这里实现的。会通过我们的配置,查找添加对应的拦截器。
    当mapping为空时,不拦截, 当mapping 不为空时,找到对应controller就添加拦截器,找不到就不添加,当设置 <mvc:mapping path="/**"/>,对所有请求添加拦截器。
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler);
        String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
        Iterator var5 = this.adaptedInterceptors.iterator();

        while(var5.hasNext()) {
            HandlerInterceptor interceptor = (HandlerInterceptor)var5.next();
            if (interceptor instanceof MappedInterceptor) {
                MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor;
                if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                    // 添加拦截器
                    chain.addInterceptor(mappedInterceptor.getInterceptor());
                }
            } else {
                // 添加拦截器
                chain.addInterceptor(interceptor);
            }
        }

        return chain;
    }

拦截器使用时机


在controller 调用之前 处理,和在 controller 调用之后处理


image.png
上一篇 下一篇

猜你喜欢

热点阅读