获取到RequestMappingHandler处理器映射器后,再获取RequestMappingHandlerAdapter处理器适配器。完成controller方法的执行。
这个是通过RequestMappingHandlerAdapter类型的类完成的。
1.获取RequestMappingHandlerAdapter
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");
}
有4个,初始化和handlerMapper相同。在第一次请求是调用方法加载。
继续调用
会发现直接返回true。然后就获取到了这个RequestMappingHandlerAdapter。
2.执行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 {
//重要方法
// 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.invokeHandlerMethod方法
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
//获取该方法的所有使用@InitBinder注解修饰的方法
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
//获取该方法的所有使用@ModelAttribute注解修饰的方法 包装成ModelFactory(包含类作用范围的和全局作用范围的)
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//上面获取@InitBinder/@ModelAttribute注解修饰的方法雷同,都是先接卸handlerMethod对应的类
//中类范围的注解修饰的方法(解析完成后放入对应的缓存),接着获取@ControllerAdvice修饰的全局范围的使用如上注解修饰的方法
//将对应的方法包装成InvocableHandlerMethod用于后面的执行,并将其包装成WebDataBinderFactory/ModelFactory对象。
//两者的区别在于ModelFactory中不仅仅包含@ModelAttribute注解修饰的方法还包含@SessionAttribute注解修饰的model处理
//同时也将上面解析出来的WebDataBinderFactory存放到modelFactory中。
//将HandlerMethod方法包装成ServletInvocableHandlerMethod(该对象是InvocableHandlerMethod子类)
//设置相关的组件 比如设置参数解析组件argumentResolvers和返回结果处理组件returnValueHandlers
//绑定组件binderFactory和parameterNameDiscoverer
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();
//对于重定向相关的参数保存需要依赖flashMap对象,如果一个请求是重定向请求 则input_flash_map保存重定向入参
//如果一个请求需要进行重定向 则参数会存放到output_flash_map中
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
//调用@ModelAttribute注解修饰的方法将对应的属性存放到mavContainer 的model中
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);
}
//通过反射执行相关的handlerMethod 涉及参数解析,返回值的处理、
//invocableMethod已经包含了进行参数解析和返回值处理的组件对象
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
//主要处理sessionAttribute 以及对model中的属性进行属性编辑器的转换处理@InitBinder
//对于view对象进行逻辑视图到物理视图的转换以及重定向参数的设置
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
4.invokeAndHandle方法
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//反射调用controller方法 获取返回值
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
disableContentCachingIfNecessary(webRequest);
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;
}
}
这个过程主要就是执行请求,包括具体的请求参数解析,返回值确定,视图解析,这三大部分。
还需要单独研究~~~~加油啊