扩展InvocableHandlerMethod ,使其能够通过注册的HandlerMethodReturnValueHandler处理返回值,还支持基于方法级别@ResponseStatus注释设置响应状态。
空返回值(包括void)可以与@ResponseStatus注释一起解释为请求处理的结束,这是一个未修改的检查条件(请参阅ServletWebRequest.checkNotModified(long)),或提供对响应流的访问的方法参数。
类图结构如下:
1. 属性和方法
1.1 returnValueHandlers属性
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
1.2 构造方法
有两个构造方法,如下所示:
public ServletInvocableHandlerMethod(Object handler, Method method);
public ServletInvocableHandlerMethod(HandlerMethod handlerMethod);
这两个构造方法都是传给父类HandlerMethod进行构造初始化,无其他业务操作。
1.2 invokeAndHandle方法
调用该方法并通过配置的HandlerMethodReturnValueHandlers之一处理返回值。
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;
}
}
2. 私有内部类ConcurrentResultHandlerMethod
ServletInvocableHandlerMethod 的一个嵌套子类,它使用一个简单的可调用的而不是原始的控制器作为处理程序,以便返回给定给它的固定(并发)结果值。使用异步生成的返回值有效地“恢复”处理。
3. InvocableHandlerMethod类
类图如下:
@Nullable
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);
}
在给定请求的上下文中解析其参数值后调用该方法。
参数值通常通过HandlerMethodArgumentResolvers解析。但是,providedArgs参数可以提供要直接使用的参数值,即不需要参数解析。提供的参数值的示例包括WebDataBinder、SessionStatus或抛出的异常实例。在参数解析程序之前检查提供的参数值。
委托给getMethodArgumentValues ,并使用已解析的参数调用doInvoke。
3.1 getMethodArgumentValues方法
获取当前请求的方法参数值,检查提供的参数值并返回到配置的参数解析器。
结果数组将被传递到doInvoke中。