Spring MVC ReturnValueHandler 原理
本文章中提及的 ReturnValueHandler 实际为 HandlerMethodReturnValueHandler
类型。
该 ReturnValueHandler
会在调用 handler 方法的时候发挥作用,其中通过以下代码注入:
1 2
| invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
|
Handler Method 处理框架
以下是 handler 方法被调用的整体流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 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; } }
|
Return Value 处理框架
若要处理返回值,需要找到合适的返回值处理器,然后调用其 handleReturnValue
方法进行处理,以下是处理返回值的整体流程代码清单:
1 2 3 4 5 6 7 8 9 10
| 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); }
|
判断 Return Value 是否支持
关于如何判断一个 ReturnValueHandler
是否支持这种返回值,主要是通过自定义实现的方法 supportsReturnType
完成,以下是挑选合适 ReturnValueHandler
的代码清单:
1 2 3 4 5 6 7 8 9 10 11 12
| private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } if (handler.supportsReturnType(returnType)) { return handler; } } return null; }
|
是否支持该返回值,具体逻辑根据不同 ReturnValueHandler
有所不同,但一般来说都是通过类型判断
应该注意到,selectHandler
会首先调用 isAsyncReturnValue
判断是否是一个异步返回值,但默认情况下,始终返回 false,因为并不存在 AsyncHandlerMethodReturnValueHandler
实例,isAsyncReturnValue
逻辑如下:
1 2 3 4 5 6 7 8 9
| private boolean isAsyncReturnValue(@Nullable Object value, MethodParameter returnType) { for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (handler instanceof AsyncHandlerMethodReturnValueHandler && ((AsyncHandlerMethodReturnValueHandler) handler).isAsyncReturnValue(value, returnType)) { return true; } } return false; }
|
Spring MVC 支持的返回值