SpringFramework版本是5.1.9
List-1
@Controller
public class UserController {
@RequestMapping("/user")
@ResponseBody
public User user(){
System.out.println("收到请求");
User alen = new User("Alen", 25);
return alen;
}
}
...
public class User {
private String name;
private int age;
...
如上所示List-1,springboot中这样使用后,会返还json数据,那么spring是怎么将User序列化后写入response的呢?
DispatcherServlet的doDispatch方法中,调用HandlerAdapter.handle方法,
AbstractHandlerMethodAdapter#handle->RequestMappingHandlerAdapter#handleInternal->invokeHandlerMethod
->ServletInvocableHandlerMethod#invokeAndHandle
List-2
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//调用controller的方法得到User
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 {
//调用ReturnValueHandler
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
如List-2所示
List-3
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
如List-3所示,HandlerMethodReturnValueHandlerComposite,看到这个类名称,就知道使用了组合模式,不用说这个类的内部一定有一个集合来存储HandlerMethodReturnValueHandler。
来看HandlerMethodReturnValueHandlerComposite的handleReturnValue方法
List-4
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
} else {
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
}
@Nullable
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
...
Iterator var4 = this.returnValueHandlers.iterator();
HandlerMethodReturnValueHandler handler;
do {
...
} while(!handler.supportsReturnType(returnType));
return handler;
}
如上List-4
HandlerMethodReturnValueHandler的实现类有15种,List-1中的情况使用哪个HandlerMethodReturnValueHandler呢?
是RequestResponseBodyMethodProcessor,我们来看它的supportsReturnType方法和handleReturnValue方法
List-5
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
...
@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.
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
...
protected ServletServerHttpResponse createOutputMessage(NativeWebRequest webRequest) {
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
Assert.state(response != null, "No HttpServletResponse");
return new ServletServerHttpResponse(response);
}
如上List-5
handleReturnValue方法中,
writeWithMessageConverters方法中,使用到HttpMessageConverter,用HttpMessageConverter来将User对象序列化,具体实现类是MappingJackson2HttpMessageConverter。writeWithMessageConverters方法内部还是和HandlerMethodReturnValueHandlerComposite一样使用到了组合,然后使用Template设计模式,所以有的人使用Fastjson来做序列化时就是自定义了HttpMessageConverter的实现,然后注册到spring容器中
一些思考,spring中有ViewResolver用来将结果渲染为页面,但是rest接口是不由ViewResolver来处理的,所以在ViewResolver那打断点,程序还没执行到那,但是结果已经返还到客户端了。