ReturnValueHandle输出原理
直接源码,接着上面学,来到handleReturnValue方法,具体被执行的这一行
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
进入后,来到方法的具体执行,方法首先是设置了一个执行第一行告诉程序当前请求已经在这个控制器方法中被处理了。去哪个方法里,能看见注释。
然后就是创建一个输入报文和输出报文,然后再用最后一行
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.
//设置请求响应值,即使是null也要尝试,这可能会涉及请求协议,就是请求时控制台里头的RequestHeader里面的Accept内容,就是请求协商【就是浏览器告诉服务器我支持什么类型的数据,你好给我显示】
//看方法名字也就知道这一句是将控制器方法返回结果转换为响应报文输出
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
进入后会来到一个很长很长的方法里,在这个方法里会实现对返回结果尝试转换为响应报文的流程
protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
Object body;
Class<?> valueType;
Type targetType;
//判断是不是字符序列,当前是一个user对象
if (value instanceof CharSequence) {
body = value.toString();
valueType = String.class;
targetType = String.class;
}
else {
//把返回值内容赋值给body【Object类型】
body = value;
//给body找返回结果类型
valueType = getReturnValueType(body, returnType);
//给body找最后转换的类型
targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass());
}
//是不是资源文件,不是
if (isResourceType(value, returnType)) {
outputMessage.getHeaders().set(HttpHeaders.ACCEPT_RANGES, "bytes");
if (value != null && inputMessage.getHeaders().getFirst(HttpHeaders.RANGE) != null &&
outputMessage.getServletResponse().getStatus() == 200) {
Resource resource = (Resource) value;
try {
List<HttpRange> httpRanges = inputMessage.getHeaders().getRange();
outputMessage.getServletR