探索Spring

Spring HandlerInterceptor使用介绍

2019-09-30  本文已影响0人  Real_man

在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:

拦截器使用

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是什么,以及如何使用。

上一篇 下一篇

猜你喜欢

热点阅读