美文网首页探索Spring
Spring HandlerInterceptor使用介绍

Spring HandlerInterceptor使用介绍

作者: Real_man | 来源:发表于2019-09-30 08:00 被阅读0次

    在Spring MVC中,HandlerMapping用于映射从请求中获取对应的Handler,一般看是否URL规则匹配,可以参考:AbstractUrlHandlerMapping#getHandlerInternal(HttpServletRequest request)的方法。然后DispatcherServlet根据获取到的Handler,找到handler对应的HandlerAdpater,HandlerAdpater传入Handler参数,内部真正的调用我们的业务方法

    在HandlerAdpater进行handler之前,之后,完成handler,我们通过HandlerInterceptor对其进行一些额外的操作。

    获取Hanlder的代码

        /**
         * Return the HandlerExecutionChain for this request.
         * <p>Tries all handler mappings in order.
         * @param request current HTTP request
         * @return the HandlerExecutionChain, or {@code null} if no handler could be found
         */
        protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            for (HandlerMapping hm : this.handlerMappings) {
                if (logger.isTraceEnabled()) {
                    logger.trace(
                            "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
                }
                HandlerExecutionChain handler = hm.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
            return null;
        }
    

    Handler.hander代码上下:

    try{
                ...
                 // 执行preHandler
                 if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
    
                    // Actually invoke the handler.
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    applyDefaultViewName(processedRequest, mv);
                    // 执行postHandler
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                    ...
    }catch (Exception ex) {
                //执行afterCompletion
                triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }
    

    HandlerIntercepter接口

    public interface HandlerInterceptor {
            // 在Handler调用之前执行,如果返回false代表Handler已经处理了这个请求,请求将被停止
            // 返回true,代表请求会交给下一个HandlerInterceptor继续处理
          boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception;
    
        //在Handler被调用之后执行,视图渲染之前,我们可以给视图加一些额外的属性
        void postHandle(
                HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
                throws Exception;
    
        // 请求完成,视图也渲染完成后
        void afterCompletion(
                HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception;
    
    }
    
    

    几个有用的HandlerInterceptor:

    • UserRoleAuthorizationInterceptor 用户是否授权拦截器
    • AsyncHandlerInterceptor 异步的HandlerInceptor
    • WebContentInterceptor 一般用于缓存Web的内容

    拦截器使用

    image-20190930075245277
    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            super.addInterceptors(registry);
            registry.addInterceptor(new LogInterceptor());
        }
    }
    

    在我们的HandlerInterceptor内部实现我们想要的业务逻辑即可:

    public class LogInterceptor implements HandlerInterceptor {
    
        private static Logger log = LoggerFactory.getLogger(LogInterceptor.class);
    
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("[preHandle][" + request + "]" + "[" + request.getMethod()
                    + "]" + request.getRequestURI() + getParameters(request));
    
            return true;
        }
    
        private String getParameters(HttpServletRequest request) {
            StringBuffer posted = new StringBuffer();
            Enumeration<?> e = request.getParameterNames();
            if (e != null) {
                posted.append("?");
            }
            while (e.hasMoreElements()) {
                if (posted.length() > 1) {
                    posted.append("&");
                }
                String curr = (String) e.nextElement();
                posted.append(curr + "=");
                if (curr.contains("password")
                        || curr.contains("pass")
                        || curr.contains("pwd")) {
                    posted.append("*****");
                } else {
                    posted.append(request.getParameter(curr));
                }
            }
            String ip = request.getHeader("X-FORWARDED-FOR");
            String ipAddr = (ip == null) ? getRemoteAddr(request) : ip;
            if (ipAddr!=null && !ipAddr.equals("")) {
                posted.append("&_psip=" + ipAddr);
            }
            return posted.toString();
        }
    
        private String getRemoteAddr(HttpServletRequest request) {
            String ipFromHeader = request.getHeader("X-FORWARDED-FOR");
            if (ipFromHeader != null && ipFromHeader.length() > 0) {
                log.debug("ip from proxy - X-FORWARDED-FOR : " + ipFromHeader);
                return ipFromHeader;
            }
            return request.getRemoteAddr();
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("[postHandle][" + request + "]");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            if (ex != null){
                ex.printStackTrace();
            }
            log.info("[afterCompletion][" + request + "][exception: " + ex + "]");
        }
    }
    
    image-20190930075854280

    最后

    主要用于快速了解Handlernterceptor是什么,以及如何使用。

    相关文章

      网友评论

        本文标题:Spring HandlerInterceptor使用介绍

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