一、dispatcherServlet的核心方法分析
当请求过来时,首先会调用到dispatcherServlet的doService方法,最终会调用到dispatcherServlet中的doDispatch方法。
该方法核心功能包含以下几点:
- WebAsyncManager异步管理
- processedRequest文件上传
- HandlerMapping根据request对象获取获取HandlerMethod和过滤器链的包装类HandlerExecutionChain
- HandlerAdapter映射关系处理,获取跟HandlerMethod匹配的HandlerAdapter对象
- applyPreHandle前置过滤器,如果为false则直接返回
- ha.handle调用到Controller具体方法,处理返回结果对象ModelAndView,核心方法调用
- applyPostHandle中置过滤器,可以对ModelAndView对象进行修改
- Render视图渲染
- afterCompletion后置过滤器,资源释放
- ExceptionHandler异常处理
1、HandlerMapping处理分析
1.1、根据请求url获取HandlerExecutionChain对象
org.springframework.web.servlet.DispatcherServlet#doDispatch
//这个方法很重要,重点看
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
寻找HandlerMethod的过程,感觉没什么好说的,前面映射关系已经建立好了,现在就是只需要从request对象中获取请求url,然后从映射关系中获取HandlerMethod对象就可以了,代码如下:
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//从request对象中获取uri,/common/query2
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
this.mappingRegistry.acquireReadLock();
try {
//根据uri从映射关系中找到对应的HandlerMethod对象
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
//把Controller类实例化
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}finally {
this.mappingRegistry.releaseReadLock();
}
}
获取过程是,先从urlLookup中
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
//建立url和RequestMappingInfo映射关系
this.urlLookup.add(url, mapping);
}
获取RequestMappingInfo对象,然后再跟进RequestMappingInfo对象从mappingLookup中
//建立uri对象和handlerMethod的映射关系
this.mappingLookup.put(mapping, handlerMethod);
获取HandlerMethod对象。
1.2、把HandlerMethod对象封装到HandlerExecutionChain对象
获取到HandlerMethod对象后,把HandlerMethod对象封装到HandlerExecutionChain对象中了。
org.springframework.web.servlet.DispatcherServlet#getHandler
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//handlerMappering实例
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
//获取HandlerMethod和过滤器链的包装类
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
1.3、获取HandlerMethod和过滤器链的包装类HandlerExecutionChain
org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//根据请求的uri拿到对应的HandlerMethod对象
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//获取HandlerMethod和过滤器链的包装类
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());
}
//是否是跨域请求,就是查看request请求头中是否有Origin属性
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
这个对象,启动就是封装了HandlerMethod和一个拦截器数组而已。
2、前置过滤器applyPreHandle
2.1、前置过滤器入口,如果为false则直接返回
org.springframework.web.servlet.DispatcherServlet#doDispatch
//前置过滤器,如果为false则直接返回
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
拿到HandlerExecutionChain对象进行过滤器的调用,调用了preHandle方法,只要这个方法返回为false,则后续请求就不会继续。
org.springframework.web.servlet.HandlerExecutionChain#applyPreHandle
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
2.2、interceptor.preHandle前置方法分析
com.chj.interceptor.UserInterceptor#preHandle
@Component
public class UserInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("======UserInterceptor用户权限校验=========");
return true;
}
2.3、如果前置返回false调用后置处理
org.springframework.web.servlet.HandlerExecutionChain#triggerAfterCompletion
/**
* Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
* Will just invoke afterCompletion for all interceptors whose preHandle invocation
* has successfully completed and returned true.
*/
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
3、核心方法ha.handle调用
3.1、HandlerAdapter调用ha.handle核心方法
进行具体Controller中方法的调用这个调用过程,返回ModelAndView对象,关键点就在于参数的解析。
org.springframework.web.servlet.DispatcherServlet#doDispatch
//调用到Controller具体方法,核心方法调用,重点看看 Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
} else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
} else {
//Controller里面具体方法调用,重点看
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
} else {
prepareResponse(response);
}
}
return mav;
}
3.2、Controller里面具体方法调用
该方法里面包括参数处理,返回对象分装处理等等。
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
//获取数据绑定工厂
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
//Model工厂
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//可调用的方法对象
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
//设置参数解析器
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
//设置返回值解析器
in