在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是什么,以及如何使用。
网友评论