SpringMVC的核心流程
-
建立请求和Controller方法的映射集合的流程。
-
根据请求查找对应的Controller方法的流程。
-
请求参数绑定到方法形参,执行方法处理请求,返回结果进行视图渲染的流程。

HandlerMapping
HandlerMapping接口作用是将请求映射到处理程序,以及预处理和处理后的拦截器列表,映射是基于一些标准的,其中的细节因不同的实现而不相同。这是官方文档上一段描述,该接口只有一个方法getHandler(request),返回一个HandlerExecutionChain对象,接口本身很简单。
public interface HandlerMapping {
String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath";
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";
// 返回请求的一个处理程序handler和拦截器interceptors
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
HandlerExecutionChain
HandlerExecutionChain 是Handler执行链,包含handler Object、interceptor。所以HandlerExecutionChain 提供了getHandler、getInterceptors方法,配置文件中配置的interceptor都会加入到HandlerExecutionChain。
public class HandlerExecutionChain {
//handler实例
private final Object handler;
//一组拦截器实例
@Nullable
private HandlerInterceptor[] interceptors;
//HandlerInterceptor的链表
@Nullable
private List<HandlerInterceptor> interceptorList;
......
}
AbstractHandlerMapping
从类图中可知,HandlerMapping主要由AbstractHandlerMapping实现。
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
implements HandlerMapping, Ordered, BeanNameAware {
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//获取handler的具体逻辑,留给子类实现
Object handler = getHandlerInternal(request);
// 如果获取到的handler为null,则采用默认的handler,即属性defaultHandler
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
//如果连DefaultHandler也为空,则直接返回空
return null;
}
// Bean name or resolved handler?
//如果handler是beanName,从容器里获取对应的bean
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//根据handler和request获取处理器链HandlerExecutionChain
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
}

-
用户发起请求,会进入到AbstractHandlerMapping类中的getHandler方法中。
-
沿着方法的调用栈发现,请求先经过FrameworkServlet的service方法去处理。
-
在由HttpServlet的service方法转发到FrameworkServlet的doPost方法中。
-
doPost方法中会调用FrameworkServlet的processRequest方法。
-
processRequest方法会调用DispatcherServlet的doService方法。
-
doService方法会调用DispatcherServlet的doDispatch方法。
-
doDispatch方法会调用到DispatcherServlet的getHandler方法。
-
DispatcherServlet的getHandler方法会调用到AbstractHandlerMapping中的getHandler方法。
DispatcherServlet#doDispatch
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//检查是否存在文件上传
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
// 根据当前request获取HandlerExecutionChain,
// HandlerExecutionChain中包含了请求url,以及对应的controller以及controller中的方法
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 通过HandlerExecutionChain获取对应的适配器,adapter负责完成参数解析
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
//处理GET、HEAD请求的Last-modified
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 遍历所有定义的 interceptor,执行 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 调用目标Controller中的方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 处理成默认视图名,也就是添加前缀和后缀等
applyDefaultViewName(processedRequest, mv);
// 拦截器postHandle方法进行处理
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 处理最后的结果,渲染之类的逻辑都在这里
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
}
DispatcherServlet#getHandler
- 根据request信息uri找到对应HandlerExecutionChain执行链,HandlerExecutionChain中包含了请求url,以及对应的controller以及controller中的方法。
public class DispatcherServlet extends FrameworkServlet {
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
}
- 该方法会依次调用DispatcherServlet类中的成员变量
List<HandlerMapping> handlerMappings
中的HandlerMapping的实现类的getHandler方法。
handlerMappings中包含4个HandlerMapping的实现类
- requestMappingHandlerMapping -> RequestMappingHandlerMapping
- beanNameHandlerMapping -> BeanNameUrlHandlerMapping
- routerFunctionMapping -> RouterFunctionMapping
- defaultServletHandlerMapping -> SimpleUrlHandlerMapping
这里主要关注RequestMappingHandlerMapping
- 因为其他的HandlerMapping实现类并不会对主流的RequestMapping注解进行处理。
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
implements HandlerMapping, Ordered, BeanNameAware {
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//获取handler的具体逻辑,留给子类实现
Object handler = getHandlerInternal(request);
// 如果获取到的handler为null,则采用默认的handler,即属性defaultHandler
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
//如果连DefaultHandler也为空,则直接返回空
return null;
}
// Bean name or resolved handler?
//如果handler是beanName,从容器里获取对应的bean
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//根据handler和request获取处理器链HandlerExecutionChain
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
}
getHandlerInternal
- 从AbstractHandlerMapping的子类方法实现里获取到真正的Handler实例。
public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo> {
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
try {
return super.getHandlerInternal(request);
}
finally {
ProducesRequestCondition.clearMediaTypesAttribute(request);
}
}
}
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 获取 request 中的 url,用来匹配 handler
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
this.mappingRegistry.acquireReadLock();
try {
// 根据路径寻找 Handler,并封装成 HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
// 根据 handlerMethod 中的 bean 来实例化 Handler,并添加进 HandlerMethod
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
}
AbstractHandlerMethodMapping#lookupHandlerMethod
- 根据路径寻找Handler,并封装成 HandlerMethod
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
// 通过 lookupPath 属性中查找。如果找到了,就返回对应的RequestMappingInfo
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
// 如果匹配到了,检查其他属性是否符合要求,如请求方法,参数,header 等
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
// 没有直接匹配到,则遍历所有的处理方法进行通配符匹配
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Match bestMatch = matches.get(0);
// 如果有多个匹配的,会找到第二个最合适的进行比较
if (matches.size() > 1) {
// 如果方法有多个匹配,不同的通配符等,则排序选择出最合适的一个
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
bestMatch = matches.get(0);
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
// 设置 request 参数(RequestMappingHandlerMapping 对其进行了覆写)
handleMatch(bestMatch.mapping, lookupPath, request);
// 返回匹配的 url 的处理的方法
return bestMatch.handlerMethod;
}
else {
// 调用 RequestMappingHandlerMapping 类的 handleNoMatch 方法再匹配一次
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
}
AbstractHandlerMapping#getHandlerExecutionChain
- 根据handler和request获取处理器链HandlerExecutionChain
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
implements HandlerMapping, Ordered, BeanNameAware {
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//判断handler是不是执行器链,如果不是则创建一个执行器链
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
//包装拦截器
/**
* <mvc:interceptor>
* <mvc:mapping path="/shopadmin/**" />
* <bean id="ShopInterceptor"
* class="com.imooc.o2o.interceptor.shopadmin.ShopLoginInterceptor" />
* </mvc:interceptor>
*/
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;
}
}
到此,根据请求查找对应的Controller方法的流程就梳理完毕了。
网友评论