美文网首页我的文章-Spring程序员
SpringMVC 拦截器 HandlerInterceptor

SpringMVC 拦截器 HandlerInterceptor

作者: 飞翔的鲲 | 来源:发表于2018-05-20 16:00 被阅读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

    相关文章

      网友评论

        本文标题:SpringMVC 拦截器 HandlerInterceptor

        本文链接:https://www.haomeiwen.com/subject/wxltjftx.html