1、HandlerMethodReturnValueHandler的调用入口。
在RequestMappingHandlerAdapter驱动ServletInvocableHandlerMethod中经过获取请求,转化成控制器方法参数和调用控制器方法参数之后,就是处理返回值的阶段。
/**
* Invoke the method and handle the return value through one of the
* configured {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers}.
* @param webRequest the current request
* @param mavContainer the ModelAndViewContainer for this request
* @param providedArgs "given" arguments matched by type (not resolved)
*/
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 {
// 使用HandlerMethodReturnValueHandlerComposite做为代理类处理返回值。
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
HandlerMethodReturnValueHandlerComposite是在RequestMappingHandlerAdapter中初始化完成的。
代码如下:
/**
* Return the list of return value handlers to use including built-in and
* custom handlers provided via {@link #setReturnValueHandlers}.
*/
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
handlers.add(new StreamingResponseBodyReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
this.contentNegotiationManager, this.requestResponseBodyAdvice));
handlers.add(new HttpHeadersReturnValueHandler());
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
// Annotation-based return value types
handlers.add(new ModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
this.contentNegotiationManager, this.requestResponseBodyAdvice));
// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// Custom return value types
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ModelAttributeMethodProcessor(true));
}
return handlers;
}
HandlerMethodReturnValueHandler接口方法如下:
HandlerMethodReturnValueHandlerComposite这个类使用了装饰模式,实现了HandlerMethodReturnValueHandler。
supportsReturnType方法如下:
/**
* Whether the given {@linkplain MethodParameter method return type} is supported by any registered
* {@link HandlerMethodReturnValueHandler}.
*/
@Override
public boolean supportsReturnType(MethodParameter returnType) {
// 通过returnType来判断是否存在支持的ReturnValueHandler
return getReturnValueHandler(returnType) != null;
}
@Nullable
private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}
handleReturnValue方法代码如下:
/**
* Iterate over registered {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers} and invoke the one that supports it.
* @throws IllegalStateException if no suitable {@link HandlerMethodReturnValueHandler} is found.
*/
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 筛选出符合条件的HandlerMethodReturnValueHandler
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
// 如果不存在则抛出IllegalArgumentException异常
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
// 执行真正的处理返回值逻辑
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
// 筛选出合适的HandlerMethodReturnValueHandler
@Nullable
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;
}
2、HandlerMethodReturnValueHandler的实现类的原理分析
####(1)、ModelAndViewMethodReturnValueHandler
该类用于支持返回值类型是ModelAndView的情况。
supportsReturnType方法如下:
@Override
public boolean supportsReturnType(MethodParameter returnType) {
// 判断returnType的类型是否是ModelAndView类型及子类。
// 这里的MethodParameter其实还是要依赖于HandlerMethod的数据。
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
}
handleReturnValue方法如下:
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 如果return直接返回,这里其实不会出现null的情况。
if (returnValue == null) {
mavContainer.setRequestHandled(true);
return;
}
ModelAndView mav = (ModelAndView) returnValue;
// 如果ModelAndView的view是String
if (mav.isReference()) {
// 获取View名称。
String viewName = mav.getViewName();
// 将View的名称设置ModelAndViewContainer中。
mavContainer.setViewName(viewName);
if (viewName != null && isRedirectViewName(viewName)) {
mavContainer.setRedirectModelScenario(true);
}
}
else {
View view = mav.getView();
mavContainer.setView(view);
if (view instanceof SmartView && ((SmartView) view).isRedirectView()) {
mavContainer.setRedirectModelScenario(true);
}
}
// 设置处理状态:HttpStatus。
mavContainer.setStatus(mav.getStatus());
// 将Model的数据也设置到ModelAndViewContainer中。
mavContainer.addAllAttributes(mav.getModel());
}
####(2)、RequestResponseBodyMethodProcessor
处理当存在@ResponseBody注解标记时。
supportsReturnType方法如下:
@Override
public boolean supportsReturnType(MethodParameter returnType) {
// 如果Controller类存在ResponseBody注解或者方法存在ResponseBody注解时处理。
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
handleReturnValue方法如下:
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
// 标记下已经处理过。
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// Try even with null return value. ResponseBodyAdvice could get involved.
// 执行参数的转化和写入到OutputStream中。
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
HandlerMethodReturnValueHandler的使用
功能:
对方法上标记@ReturnValue的注解自动转化成json,这里只是个例子,具体可以根据需求来改造。
(1)、首先自定义一个HandlerMethodReturnValueHandler
public class MyMethodReturnValueResolver implements HandlerMethodReturnValueHandler {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
// 参数的方法需要被@ReturnValue注解标记
return returnType.hasMethodAnnotation(ReturnValue.class);
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 将requestHandled置为true。表示已经处理完成,不再需要被模版解析。
mavContainer.setRequestHandled(true);
String result = JSON.toJSONString(returnValue);
// 获取HttpServletResponse对象。
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
ServletServerHttpResponse servletServerHttpResponse = new ServletServerHttpResponse(response);
servletServerHttpResponse.getBody().write(result.getBytes());
// 关闭并刷新流。
servletServerHttpResponse.getBody().close();
servletServerHttpResponse.getBody().flush();
}
}
(2)、将MyMethodReturnValueResolver对象设置到RequestMappingHandlerAdapter中。
@PostConstruct
public void init() {
MyMethodReturnValueResolver myMethodReturnValueResolver = new MyMethodReturnValueResolver();
List<HandlerMethodReturnValueHandler> handlerMethodReturnValueHandlers = new ArrayList<>();
handlerMethodReturnValueHandlers.add(myMethodReturnValueResolver);
handlerMethodReturnValueHandlers.addAll(requestMappingHandlerAdapter.getReturnValueHandlers());
requestMappingHandlerAdapter.setReturnValueHandlers(handlerMethodReturnValueHandlers);
}
(3)、使用:
@RequestMapping("fast")
@ReturnValue
public AmdCpu fast() {
AmdCpu amdCpu = new AmdCpu();
amdCpu.setType("gaoming");
amdCpu.setName("gaoming");
amdCpu.setNumber(1111);
AmdMainBoard amdMainBoard = new AmdMainBoard();
amdMainBoard.setSize(123L);
amdCpu.setMainBoard(amdMainBoard);
return amdCpu;
}
结果如下:
{
"mainBoard": {
"name": "amd main board",
"size": 123
},
"name": "gaoming",
"number": 1111,
"type": "gaoming"
}
这里仅仅介绍了平时开发中会遇到的处理器。