之前也已经总述过:AOP执行原理、SpringMvc执行流程,但总觉的有些点说的含糊不清,后续就把含糊不清的点,细致的讲解一下。现在先说请求核心处理doDispatch()方法。
上图是默认容器启动后IOC装载的:HandlerAdapters和HandlerMapping(有印象,后续用)。
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);
//1. 获取handler执行器链HandlerExecutionChain.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//2. 获取目标handler适配器HandlerAdapter执行目标Handler
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
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;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//3. 执行目标Handler,返回ModelAndView.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
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()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
图中标的1-3,就是我们常说的主要执行流程。根据mvc执行图,脑海中会有简单清晰的执行流程。但现在主要阐述这三步具体的执行流程:
1. mappingHandler = getHandler(processedRequest);
DispatcherServlet.java中: 遍历已经装载的默认的HandlerMaping
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;
}
AbstractHandlerMapping.java中: 查找目标Handler,并添加拦截器。(给HandlerExecuterChain中 [private List<HandlerInterceptor> interceptorList;] 属性赋值)
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request); <-----
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
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 (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;
}
AbstractHandlerMethodMapping.java中: 根据uri查找目标Handler方法。(给HandlerExecuterChain中 [private final Object handler;] 属性赋值)
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
2. HandlerAdapter ha = getHandlerAdapter(mappingHandler.getHandler());
DispatcherServlet.java中: 遍历装载的HandlerAdapter(开头debug容器装载图),获取支持当前handler的HandlerAdapter.
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
3. mv = ha.handler(processedRequest,response,mappingHandler.getHandler());
1. AbstactHandlerMappingAdapter.java中: (HandlerAdapter类图: xxxHandlerAdapter extends AbstactHandlerMappingAdapter implements HandlerAdapter)
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler); <---------
}
2. RequestMappingHandlerAdapter.java中:
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
//检测是否需要加锁执行synchronize
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
//Spring自带的WebUtils工具类
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}else {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}else {
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. RequestMappingHandlerAdapter.java中:(doDispatch()上面挑选的HandlerMappingAdapter) 对于mv这步,暂时不讲述
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//主要看这个类的动作
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
LogFormatUtils.traceDebug(logger, traceOn -> {
String formatted = LogFormatUtils.formatValue(result, !traceOn);
return "Resume with async result [" + formatted + "]";
});
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
invocableMethod.invokeAndHandle(webRequest, mavContainer); <------------
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
4. ServletInvocableHandlerMethod.java : 调用该方法并通过已配置的方法之一处理返回值(ServletInvocableHandlerMethod extends InvocableHandlerMethod)
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//执行方法,返回结果,或许再根据已注册的HandlerMethodReturnValueHandler解析
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); <------------
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
}else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
5. InvocableHandlerMethod.java :
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//参数解析,将url中的参数值解析
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
//利用JavaReflect完成方法调用
return doInvoke(args);
}
6. InvocableHandlerMethod.java :
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
//检测、使用参数解析器HandlerMethodArgumentResolver解析参数
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}catch (Exception ex) {
// Leave stack trace for later, e.g. AbstractHandlerExceptionResolver
if (logger.isDebugEnabled()) {
String message = ex.getMessage();
if (message != null && !message.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, message));
}
}
throw ex;
}
}
if (args[i] == null) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
}
return args;
}
整个流程貌似可以说的通,再屡一下,很容易发现,没有对已经装载的参数解析器,进行遍历的代码。
真的没有吗?
再去看一下最后InvocableHandlerMethod.getMethodArgumentValues()方法,其中有段代码有检测的
是否支持已装载的参数解析器:if(this.argumentResolvers.supportsParameter(parameter))。顺着
这条再去看一下InvocableHandlerMethod类中argumentResolvers属性类型,会发现是使用混合模型的
对象:HandlerMethodArgumentResolverComposite argumentResolvers。这样很容易发现,遍历参数解
析器的操作是在HandlerMethodArgumentResolverCompoiste中执行。
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
//这个argumentResolverCache,是优化请求处理,使用的缓存:Map<MethodParameter, HandlerMethodArgumentResolver>
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
if (methodArgumentResolver.supportsParameter(parameter)) {
result = methodArgumentResolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
HandlerAdapter:(HandlerAdapter子类需要实现HandlerAdapter接口,并实现supports(Object handler)方法,而supports()方法返回boolean类型,决定了当前HandlerAdapter是否支持使用。)
RequestMappingHandlerAdapter: handler方法使用@RequestMapping、@Controller等注解
SimpleControllerHandlerAdapter: handler类实现Controller接口
HttpRequestHandlerAdapter:handler类实现HttpRequetHandler接口
HandlerMapping:(上面已经截图)
HandlerMethodArgumentResolver:RequestMappingHandlerAdapter.getDefaultArgumentResolvers()。
参考文章: https://www.cnblogs.com/w-y-c-m/p/8443892.html
//默认的参数解析,创建了默认的24个参数解析器,并添加至resolvers
//这里的24个参数解析器都是针对不同的参数类型来解析的
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
// 基于注解的参数解析器
//一般用于带有@RequestParam注解的简单参数绑定,简单参数比如byte、int、long、double、String以及对应的包装类型
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
//用于处理带有@RequestParam注解,且参数类型为Map的解析绑定
resolvers.add(new RequestParamMapMethodArgumentResolver());
//一般用于处理带有@PathVariable注解的默认参数绑定
resolvers.add(new PathVariableMethodArgumentResolver());
//也是用于带有@PathVariable注解的Map相关参数绑定,后续还有一些默认的参数解析器。后续还有一些参数解析器,我这里都不一一解释了。想具体确认某个参数会交个哪个参数解析器处理,可以通过以下解析器的supportsParameter(MethodParameter parameter)方法得知
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// 基于类型的参数解析器
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
常见使用场景:SpringBoot中implement WebMvcConfigurer具体实现相关配置
1. 拦截器Interceptor
2. 参数解析器HandlerMethodArgumentResolver
&3.消息转换器MessageConverters
流程体会:
1. 父类接口、抽象类、实现类: 模板设计模型
2. 混合设计模式: 参考 HandlerMethodArgumentResolverComposite (实现父类方法,并设置父类集合作为属性)
3. Spring中自带的一些工具类的使用