ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
:执行目标方法
执行完成会返回一个ModelAndView
对象,如果是前后端不分离ModelAndView
就会有值,如果是前后端分离返回json格式的数据的话ModelAndView
就没有值。json是直接通过response写出去了
invokeHandlerMethod()
再上一篇拿到的HandlerAdapter
是RequestMappingHandlerAdapter
,这个类中的invokeHandlerMethod()
是执行目标方法的核心。我们直接来分析这个方法
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
// 1、把request和response封装起来
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) {
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;
}
// 得到ModelAndView对象
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
流程:
-
创建了一个
ServletInvocableHandlerMethod
(目标方法的处理器),它扩展了InvocableHandlerMethod
,它又扩展了HandlerMethod
HandlerMethod
就是我们之前拿到的目标方法,也就是处理器InvocableHandlerMethod
使其支持能够通过HandlerMethodArgumentResolver
来解析参数ServletInvocableHandlerMethod
使其支持能够通过HandlerMethodReturnValueHandler
来处理返回值、@ResponseStatus
注解 等等功能
-
一堆初始化工作:数据绑定器工厂、Model工厂、参数解析器、返回值处理器
-
异步的工作
-
调用
invokeAndHandle()
执行目标方法
invokeAndHandle()
执行目标方法
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()
:执行目标方法拿到返回值- 利用参数解析器来解析请求携带的参数的值
- 利用反射执行目标方法
returnValueHandlers.handleReturnValue()
:遍历所有返回值处理器,使用返回值处理器处理返回值
invokeForRequest()
执行目标方法
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()
使用参数解析器来解析请求携带的参数的值 HandlerMethodArgumentResolver
// 参数解析器的组合,里面封装了所有参数解析器
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 1、获取目标方法所有的参数
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
Object[] args = new Object[parameters.length];
// 2、遍历目标方法所有的参数
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
// 3、使用参数解析器解析判断是否支持解析这种参数
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
// 4、使用参数解析器来解析参数
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
}
catch (Exception ex) {
// 5、如果有异常
// 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;
}
其实核心就是利用各种参数解析器来解析参数的值,所以我们把参数解析器搞明白就知道了。
-
调用
getMethodParameters()
获取目标方法上的所有参数 -
遍历目标方法上所有的参数,并把传递过来的参数的值绑定到对应的参数上
-
this.resolvers.supportsParameter()
:遍历所有参数解析器,调用其supportsParameter()
来判断是否支持解析此参数,如果支持就放入缓存中,然后返回- 其实就是判断对应的参数上有没有对应的注解修饰:
@RequestParam
、@PathVariable
、...
- 其实就是判断对应的参数上有没有对应的注解修饰:
-
this.resolvers.resolveArgument()
:从缓存中拿到上一步放入的参数解析器,然后调用其resolveArgument()
来解析参数
-
2.1、this.resolvers.supportsParameter(parameter)
// 参数解析器的缓存
private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
new ConcurrentHashMap<>(256);
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
// 先从缓存中拿,缓存中没有再遍历
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
// 调用参数解析器的supportsParameter()判断是否支持处理这种类型的参数
if (resolver.supportsParameter(parameter)) {
result = resolver;
// 放到缓存中
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
2.2、this.resolvers.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);
}
默认是有27个参数解析器
反射执行目标方法-doInvoke()
就是使用反射来执行目标方法
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 利用反射给目标方法携带参数,然后执行目标方法
return getBridgedMethod().invoke(getBean(), args);
}
// 省略代码
...
}
返回值处理器处理返回值-handleReturnValue()
使用返回值处理器来处理返回值 HandlerMethodReturnValueHandler
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()
得到一个返回值处理器 - 调用返回值处理器的
handleReturnValue()
来处理返回值
15个返回值处理器
具体的参数解析原理和返回值处理原理放在单独的文章来说,逻辑太多。
返回值处理原理:SpringMVC原理(7)-返回值的处理
参数解析原理:SpringMVC原理(6)-参数解析原理
总结
执行目标方法流程:
- 利用参数解析器来解析请求参数的值
- 执行目标方法
- 利用返回值处理器来处理返回值
HandlerMethod
HandlerMethod
就是我们之前拿到的目标方法,也就是处理器InvocableHandlerMethod
使其支持能够通过HandlerMethodArgumentResolver
来解析参数ServletInvocableHandlerMethod
使其支持能够通过HandlerMethodReturnValueHandler
来处理返回值、@ResponseStatus
注解 等等功能