该源码分析系列文章分如下章节:
- springmvc源码分析(1)-- DispatcherServlet
- springmvc源码分析(2)-- HandlerMapping
- springmvc源码分析(3)-- HandlerAdapter
- springmvc源码分析(3.1)-- HandlerMethodReturnValueHandler
- springmvc源码分析(4)-- ViewResolver
该接口的调用请参考springmvc源码分析(3)-- HandlerAdapter
本章只分析该接口的一些用法和常用实现类
该接口有两个方法
public interface HandlerMethodReturnValueHandler {
/**
* Whether the given {@linkplain MethodParameter method return type} is
* supported by this handler.
* @param returnType the method return type to check
* @return {@code true} if this handler supports the supplied return type;
* {@code false} otherwise
*/
boolean supportsReturnType(MethodParameter returnType);
/**
* Handle the given return value by adding attributes to the model and
* setting a view or setting the
* {@link ModelAndViewContainer#setRequestHandled} flag to {@code true}
* to indicate the response has been handled directly.
* @param returnValue the value returned from the handler method
* @param returnType the type of the return value. This type must have
* previously been passed to {@link #supportsReturnType} which must
* have returned {@code true}.
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @throws Exception if the return value handling results in an error
*/
void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}
supportsReturnType表示支持的return类型
handleReturnValue执行实际逻辑
该接口实现默认有n多个,在处理器适配器初始化bean时执行afterPropertiesSet进行构建,我们直接从RequestMappingHandlerAdapter该适配器里开始: 这里我们可以看到进行获取默认HandlerMethodReturnValueHandler列表,getDefaultReturnValueHandlers调用:
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;
}
这里面可以看到添加了很多个默认实现类,其中也包括用户自定义的:
我们拿出几个常用到的来分析下:
1.ModelAndViewMethodReturnValueHandler:
这里可以看到支持的返回类型为ModelAndView,当controller执行后返回类型是ModelAndView的,那么将采用该类的handleReturnValue方法进行结果处理:
public boolean isReference() {
return (this.view instanceof String);
}
这里处理比较简单直接判断返回的返回的view是否String,是则将视图的名字放入视图容器里,然后接着判断是否重定向是则
setRedirectModelScenario(true)
如果view非String,获取视图对象放入视图容器里然后接着判断是否重定向。
2.RequestResponseBodyMethodProcessor:
这里判断仅支持有@ResponseBody注解的返回,也就是我们的接口json返回,那么将用其handleReturnValue调用对我们结果处理:
设置标识mavContainer.setRequestHandled(true);
接着writeWithMessageConverters,其实调用该方法已经完成进行结果输出了,也就是对浏览器进行响应输出,因为是json,所以不需要进入视图解析器渲染,所以直接输出即可。
当然我们也是可以自定义HandlerMethodReturnValueHandler,在springmvc实用篇 -- WebMvcConfigurer这一章中我们有提到过里面有很多自定义配置供我们添加,其中就有HandlerMethodReturnValueHandler的添加,下面我们来试一下:
1.实现WebMvcConfigurer:
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
handlers.add(0, new HandlerMethodReturnValueHandler() {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return UserA.class.isAssignableFrom(returnType.getParameterType()) ;
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
mavContainer.setRequestHandled(true);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
response.getWriter().println("diyReturnValueHandlers:"+returnValue);
}
});
}
}
这里我们设定该返回值处理仅适合UserA,然后进入处理,将结果直接输出到浏览器,mavContainer.setRequestHandled(true)表示不再视图解析
2.创建controller让其返回UserA
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/user")
public UserA user() {
return new UserA("cwh",22);
}
}
3.访问结果:
ok,一切在我们掌握之中