1.写在前面
笔者前面已经介绍过了如何获取对应的Handler
,以及如何获取对应的HandlerAdapter
,也就是从Url和方法的映射到找到对应的适配器,笔者已经讲完了。接下笔者讲的是如何调用,以及视图的解析。今天这篇博客要讲的就是HandlerAdapter
的调用
2.HandlerAdapter的调用
笔者还是带大家看下原来的代码,具体的内容如下:
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.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
//判断这个方法是get还是其他的方法
String method = request.getMethod();
boolean isGet = "GET".equals(method);
//若是get或者head执行下面的操作
if (isGet || "HEAD".equals(method)) {
//默认的情况下都是返回-1
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
//一般的情况下不会进入
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//处理拦截器的方法,调用拦截器的preHandle方法,如果被拦截就直接返回
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 本篇博客的重点
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//省略一部分代码
}
}
}
上面的代码先是调用拦截器的方法,如果被拦截下来了,就直接结束这个方法,如果没有被拦截,就执行对应的HandlerAdapter
的中的handle
方法。同样这儿也是有四个HandlerAdapter
的方法要看。
2.1HttpRequestHandlerAdapter
这个类结构,笔者在上篇博客已经介绍,笔者在这里就不赘述了。我们还是看核心的handle
方法,具体的代码如下:
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//调用对应的实现类中handleRequest方法
((HttpRequestHandler) handler).handleRequest(request, response);
//返回值为空
return null;
}
笔者再来带大家看下测试代码,具体的如下:
package com.ys.controller;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component("/httpRequest.do")
public class HttpRequestHandlerController implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("hello");
}
}
所以这种就很简单,就直接调用对应实现HttpRequestHandler
接口的handleRequest()
方法。
2.2SimpleControllerHandlerAdapter
废话不多说,直接看SimpleControllerHandlerAdapter
这个类的handle
方法,具体的代码如下:
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//调用对应类的handleRequest方法
return ((Controller) handler).handleRequest(request, response);
}
再来看下测试的代码,具体的如下:
package com.ys.controller;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component("/beanName.do")
public class BeanNameController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
return new ModelAndView("index");
}
}
所以这种就很简单,就直接调用对应实现Controller
接口的handleRequest()
方法,同时这个方法的方法的返回值ModelAndView
对象
2.3HandlerFunctionAdapter
这个类的handle()
方法的代码如下:
public ModelAndView handle(HttpServletRequest servletRequest,
HttpServletResponse servletResponse,
Object handler) throws Exception {
HandlerFunction<?> handlerFunction = (HandlerFunction<?>) handler;
ServerRequest serverRequest = getServerRequest(servletRequest);
ServerResponse serverResponse = handlerFunction.handle(serverRequest);
return serverResponse.writeTo(servletRequest, servletResponse,
new ServerRequestContext(serverRequest));
}
这块是webflux的知识,笔者后面会专门写一篇博客来介绍这块的内容,这儿暂且跳过吧。我们来看最后一个HandlerAdapter
2.4RequestMappingHandlerAdapter
照例还是先看handle()
方法,具体的代码如下:
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
发现直接调用的是handleInternal()
方法,具体的代码如下:
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
//检查请求的会话是否支持
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
//默认的情况下这个值是false,所以会执行else中的代码
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;
}
上面会调用Url映射的方法,主要是invokeHandlerMethod(request, response, handlerMethod);
具体的代码如下:
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//将request和response包装成ServletWebRequest对象
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
//返回Web数据绑定器工厂
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
//返回模型工厂
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//返回要调用的方法
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
//设置参数的解析器
if (this.argumentResolvers != null) {
//之前在调用afterPropertiesSet方法初始化的
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
//设置方法的返回类型参数
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
//设置对应的Web数据绑定器工厂
invocableMethod.setDataBinderFactory(binderFactory);
//设置对应的方法参数名发现器,就是用来查找方法的参数的名称的,因为jdk自带只会返回arg0
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
//创建模型和视图的容器
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
//设置只读的input的属性
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;
}
//获取对应的modelAndView对象
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
上面就进行一系列的参数的赋值,最后真正调用方法的是invokeAndHandle(webRequest, mavContainer);
方法,具体的代码如下:
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//调用方法的逻辑
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;
}
}
上面的代码最终调用映射的方法处理逻辑主要是在invokeForRequest(webRequest, mavContainer, providedArgs);
具体的代码如下:
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//处理参数
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
//通过反射调用方法
return doInvoke(args);
}
上面的代码主要是通过getMethodArgumentValues(request, mavContainer, providedArgs);
方法来获取参数,以及设置对应的参数,最后调用doInvoke(args);
来执行对应的方法,主要是通过反射来调用。笔者先带大家看下处理参数的方法,具体的代码如下:
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//获取方法的参数
MethodParameter[] parameters = getMethodParameters();
//如果参数为空,直接返回空对象数组
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
//初始化参数名称的发现器
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
//这儿一般的情况下会返回null
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
//查找对应的参数的处理器,主要是遍历所有的参数的处理器,调用处理中的support方法,只要满足就返回true
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
}
catch (Exception ex) {
// Leave stack trace for later, exception may actually be resolved and handled...
if (logger.isDebugEnabled()) {
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
throw ex;
}
}
return args;
}
我们可以看下resolvers.supportsParameter(parameter)
,这个方法主要是查找指定的参数匹配器。具体的代码如下:
public boolean supportsParameter(MethodParameter parameter) {
return getArgumentResolver(parameter) != null;
}
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
//先获取一篇参数的处理器
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
//如果参数的处理器为空
if (result == null) {
//遍历所有的参数处理器,调用每一个参数处理器的supportsParameter方法,直达返回的结果为true为止
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
if (resolver.supportsParameter(parameter)) {
result = resolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
这个参数处理器的列表初始化,笔者在上篇博客中已经讲了,主要是通过调用afterPropertiesSet方法中来初始化的,具体的代码如下:
private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(20);
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new SessionAttributeMethodArgumentResolver());
resolvers.add(new RequestAttributeMethodArgumentResolver());
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
return resolvers;
}
注意上面是加了两个RequestParamMethodArgumentResolver
对象,只不过第一次的参数的值是false,第二次参数的值为true。那么这个两个值的区别是啥?我们还需要看RequestParamMethodArgumentResolver
类的supportsParameter
方法,具体的代码如下:
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.hasParameterAnnotation(RequestParam.class)) {
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
return (requestParam != null && StringUtils.hasText(requestParam.name()));
}
else {
return true;
}
}
else {
if (parameter.hasParameterAnnotation(RequestPart.class)) {
return false;
}
parameter = parameter.nestedIfOptional();
if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
return true;
}
//区别在这,如果是true的话,基本的类型是会返回true,如果不是true,就直接跳过
else if (this.useDefaultResolution) {
return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
}
else {
return false;
}
}
}
区别就在于如果是true的话,基本的类型是会返回true,如果不是true,就直接跳过,所以上面在调用所有参数的处理器中的supportsParameter方法的时候,第一次RequestParamMethodArgumentResolver
是匹配不成功,只有第二次的时候才能匹配成功,因为这个useDefaultResolution
值第二次的时候为true。既然找对应的参数处理器的规则已经搞懂了,我们继续看原来的代码。
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//获取方法的参数
MethodParameter[] parameters = getMethodParameters();
//如果参数为空,直接返回空对象数组
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
//初始化参数名称的发现器
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
//这儿一般的情况下会返回null
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
//查找对应的参数的处理器,主要是遍历所有的参数的处理器,调用处理中的support方法,只要满足就返回true
if (!this.resolvers.supportsParameter(parameter)) {//如果这儿没有找到对应的参数处理器的话,就直接抛出异常
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
//找到了就直接执行参数处理器的resolveArgument方法
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
}
catch (Exception ex) {
// Leave stack trace for later, exception may actually be resolved and handled...
if (logger.isDebugEnabled()) {
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
throw ex;
}
}
return args;
}
这个时候如果没有找到对应的参数处理器的话,就直接抛出异常,如果找到了就执行这个参数处理器的resolveArgument
方法,具体的代码如下:
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException("Unsupported parameter type [" +
parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
}
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
然后调用这个参数处理器的resolveArgument
的方法,我们继续跟进,具体的代码如下:
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
//获取方法的参数的名称
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
//获取包装的方法的参数的类型
MethodParameter nestedParameter = parameter.nestedIfOptional();
//解析这个字符串的值
Object resolvedName = resolveStringValue(namedValueInfo.name);
if (resolvedName == null) {
throw new IllegalArgumentException(
"Specified name must not resolve to null: [" + namedValueInfo.name + "]");
}
//调用子类RequestParamMethodArgumentResolver来获取参数的值
Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
if (arg == null) {//获取的值为空
if (namedValueInfo.defaultValue != null) {//查看是否有默认值,设置默认值
arg = resolveStringValue(namedValueInfo.defaultValue);
}
else if (namedValueInfo.required && !nestedParameter.isOptional()) {//判断是否是必须要值,如果是直接抛出异常
handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
}
//处理空值,如果这个值的类型是Boolean类型,就设置为false,其他的情况下都是原来的默认值
arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
}
else if ("".equals(arg) && namedValueInfo.defaultValue != null) { //获取值为“”同时默认值也不为空,那么就将默认值设置进去
arg = resolveStringValue(namedValueInfo.defaultValue);
}
//下面是进行对应的参数的转换,因为接受过来的一般都是string的类型
if (binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
try {
arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
}
catch (ConversionNotSupportedException ex) {
throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
namedValueInfo.name, parameter, ex.getCause());
}
catch (TypeMismatchException ex) {
throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
namedValueInfo.name, parameter, ex.getCause());
}
}
//这儿不没有重写对应的方法,所以是个空的方法。
handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
//返回处理好的参数的
return arg;
}
由于RequestParamMethodArgumentResolver
类没有实现HandlerMethodArgumentResolver
接口,所以这儿调用的是父类的resolveArgument
方法,但是获取对应参数的值是调用子类RequestParamMethodArgumentResolver
的resolveName
方法,具体的代码如下:
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
if (servletRequest != null) {
Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
return mpArg;
}
}
Object arg = null;
//处理文件的
MultipartRequest multipartRequest = request.getNativeRequest(MultipartRequest.class);
if (multipartRequest != null) {
List<MultipartFile> files = multipartRequest.getFiles(name);
if (!files.isEmpty()) {
arg = (files.size() == 1 ? files.get(0) : files);
}
}
if (arg == null) {
//还是用servlet的api
String[] paramValues = request.getParameterValues(name);
if (paramValues != null) {
arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
}
}
return arg;
}
我们终于看到对应的参数的获取的方法,就是利用了servlet的api来获取指定的参数的值的。最后返回出去。最后就是通过反射调用对应的方法,我们继续看剩下的代码
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
//设置响应的状态码,这儿应该没有调用完,会是null
setResponseStatus(webRequest);
//如果返回值为空
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
//禁用缓存
disableContentCachingIfNecessary(webRequest);
//将这个变量设置为true
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {//这个有值
//将这个变量设置为true
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;
}
}
上面的代码会调用handleReturnValue()
,具体的代码如下:
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
//查找指定的方法返回值的处理器
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
//调用指定的方法返回值的处理器中这个方法
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
上面的代码主要是通过selectHandler(returnValue, returnType);
来查找对应的方法返回值的处理器,具体的代码如下:
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
//判断是否是异步
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
//遍历所有的方法返回值的处理器的supportsReturnType方法,只要找到匹配的就直接返回
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}
这儿原理和上面的找方法参数的处理器的机制差不多,都是遍历所有的处理器,调用对应处理器的supportsReturnType
方法,一旦满足条件的话,就直接返回。至此整个方法的调用的过程就讲完了,简单总结一下:先根据方法的参数,遍历所有的参数处理器,分别调用处理器中的supportsParameter方法,如果满足了就直接返回这个参数处理器,然后调用这个参数处理器的resolveArgument
方法,最后还有对方法的返回值进行处理,还是一样的先是遍历所有返回值处理器的,并且调用这些处理器中的supportsReturnType
方法,如果满足的话,就直接返回这个处理器,同时会调用这个处理器的handleReturnValue
方法对方法的返回值进行处理和封装。最后调用的getModelAndView()
方法,具体的代码如下:
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
modelFactory.updateModel(webRequest, mavContainer);
//判断这个值是否是true,一般返回的如果不是视图的话,这个值就是true
if (mavContainer.isRequestHandled()) {
return null;
}
ModelMap model = mavContainer.getModel();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
if (request != null) {
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
}
return mav;
}
上面的代码获取的ModelAndView
并不是真正的模型视图对象,这个笔者后面的博客会讲清楚。然后就返回到对应代码地方,具体的如下:
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//省略一部分代码
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.写在最后
这边博客主要讲了调用几大HandlerAdapter的handle的调用的过程,已经其中的处理逻辑,后面的博客就要讲视图的解析的过程。