擴(kuò)展InvocableHandlerMethod 躲雅,使其能夠通過注冊(cè)的HandlerMethodReturnValueHandler處理返回值诵闭,還支持基于方法級(jí)別@ResponseStatus注釋設(shè)置響應(yīng)狀態(tài)缅糟。
空返回值(包括void)可以與@ResponseStatus注釋一起解釋為請(qǐng)求處理的結(jié)束价捧,這是一個(gè)未修改的檢查條件(請(qǐng)參閱ServletWebRequest.checkNotModified(long))饭耳,或提供對(duì)響應(yīng)流的訪問的方法參數(shù)偶垮。
類圖結(jié)構(gòu)如下:
1. 屬性和方法
1.1 returnValueHandlers屬性
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
1.2 構(gòu)造方法
有兩個(gè)構(gòu)造方法遗增,如下所示:
public ServletInvocableHandlerMethod(Object handler, Method method);
public ServletInvocableHandlerMethod(HandlerMethod handlerMethod);
這兩個(gè)構(gòu)造方法都是傳給父類HandlerMethod進(jìn)行構(gòu)造初始化叫惊,無其他業(yè)務(wù)操作。
1.2 invokeAndHandle方法
調(diào)用該方法并通過配置的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. 私有內(nèi)部類ConcurrentResultHandlerMethod
ServletInvocableHandlerMethod 的一個(gè)嵌套子類霍狰,它使用一個(gè)簡(jiǎn)單的可調(diào)用的而不是原始的控制器作為處理程序抡草,以便返回給定給它的固定(并發(fā))結(jié)果值。使用異步生成的返回值有效地“恢復(fù)”處理蔗坯。
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);
}
在給定請(qǐng)求的上下文中解析其參數(shù)值后調(diào)用該方法康震。
參數(shù)值通常通過HandlerMethodArgumentResolvers解析。但是宾濒,providedArgs參數(shù)可以提供要直接使用的參數(shù)值腿短,即不需要參數(shù)解析。提供的參數(shù)值的示例包括WebDataBinder绘梦、SessionStatus或拋出的異常實(shí)例橘忱。在參數(shù)解析程序之前檢查提供的參數(shù)值。
委托給getMethodArgumentValues 卸奉,并使用已解析的參數(shù)調(diào)用doInvoke钝诚。
3.1 getMethodArgumentValues方法
獲取當(dāng)前請(qǐng)求的方法參數(shù)值,檢查提供的參數(shù)值并返回到配置的參數(shù)解析器榄棵。
結(jié)果數(shù)組將被傳遞到doInvoke中凝颇。