再次来回顾下Spring mvc的请求映射流程吧,首先,客户端发送请求被DispathcerServlet拦截,然后把请求作为参数调用handlerMappings找到对应的HandlerMapping得到Handler封装成HandlerExecutionChain对象返回给DispatcherServlet处理器。
1. HandlerMapping接口
接口定义如下
public interface HandlerMapping {
String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
从接口定义中可以发现,该接口只有一个抽象方法getHandler,返回参数为一个HandlerExecutionChain对象。
image.png
MatchableHandlerMapping接口通过继承HandlerMapping接口,增加了新的match抽象方法,
@Nullable
RequestMatchResult match(HttpServletRequest request, String pattern);
该方法作用是在确定给定的请求是否符合请求条件
2 Handler映射执行流程
image.png获取到Handler对象后封装成HandlerExecutionChain对象的核心代码:
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
3. 自定义拦截器
实现拦截器的步骤:
- 实现HandlerInterceptor 接口
- 注册到Spring容器中
3.1 实现方案
HandlerInterceptor的接口定义如下:
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
自定义拦截器必须实现该接口,下面自定义拦截器代码:
public class TestHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
实现Springboot 自动配置拦截器
package com.joe.code.common.configuration;
import com.joe.code.common.component.TestResolver;
import com.joe.code.common.intercepter.TestHandlerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
// 注册resolver
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Autowired
private ApplicationContext context;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestHandlerInterceptor());
}
}
网友评论