主要是 @ResponseBody
注解的处理流程。@ResponseBody
用于将方法的返回值直接写入 HTTP 响应体中,而不是渲染视图。它的核心逻辑与 @RequestBody
类似,但方向相反:将 Java 对象转换为 HTTP 响应体内容。
1. @ResponseBody
的处理入口:RequestMappingHandlerAdapter
@ResponseBody
的处理同样由 RequestMappingHandlerAdapter
完成。在 invokeHandlerMethod
方法中,RequestMappingHandlerAdapter
会调用 ServletInvocableHandlerMethod
来执行目标方法,并处理返回值。
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {// 1. 创建 ServletInvocableHandlerMethod 对象ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);// 2. 设置返回值处理器(HandlerMethodReturnValueHandler)invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);// 3. 调用目标方法并处理返回值invocableMethod.invokeAndHandle(webRequest, mavContainer);// 4. 返回 ModelAndView(如果返回值是视图)return getModelAndView(mavContainer, modelFactory, webRequest);
}
2. 返回值处理的核心:HandlerMethodReturnValueHandler
HandlerMethodReturnValueHandler
是 Spring MVC 中用于处理方法返回值的接口。@ResponseBody
注解的处理由 RequestResponseBodyMethodProcessor
完成。
2.1 HandlerMethodReturnValueHandler
接口
public interface HandlerMethodReturnValueHandler {// 判断是否支持当前返回值类型boolean supportsReturnType(MethodParameter returnType);// 处理返回值void handleReturnValue(Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}
2.2 RequestResponseBodyMethodProcessor
的实现
RequestResponseBodyMethodProcessor
不仅实现了 HandlerMethodArgumentResolver
,还实现了 HandlerMethodReturnValueHandler
,用于处理 @ResponseBody
注解。
public class RequestResponseBodyMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {@Overridepublic boolean supportsReturnType(MethodParameter returnType) {// 判断方法是否带有 @ResponseBody 注解return returnType.hasMethodAnnotation(ResponseBody.class);}@Overridepublic void handleReturnValue(Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {// 1. 标记请求已处理,不需要视图渲染mavContainer.setRequestHandled(true);// 2. 获取 HttpServletResponse 对象HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);// 3. 使用 HttpMessageConverter 将返回值写入响应体writeWithMessageConverters(returnValue, returnType, webRequest, response);}
}
3. 返回值写入响应体:HttpMessageConverter
RequestResponseBodyMethodProcessor
使用 HttpMessageConverter
将 Java 对象转换为 HTTP 响应体内容。常用的 HttpMessageConverter
包括:
MappingJackson2HttpMessageConverter
:用于将对象转换为 JSON 字符串。StringHttpMessageConverter
:用于将字符串直接写入响应体。
3.1 writeWithMessageConverters
方法
protected <T> void writeWithMessageConverters(T value, MethodParameter returnType,NativeWebRequest webRequest, HttpServletResponse response) throws IOException {// 1. 获取请求和响应的媒体类型(Content-Type)HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);HttpHeaders headers = new HttpHeaders();MediaType contentType = getContentType(request, response);// 2. 遍历所有的 HttpMessageConverter,找到支持当前返回值类型的转换器for (HttpMessageConverter<?> converter : this.messageConverters) {if (converter.canWrite(returnType.getParameterType(), contentType)) {// 3. 使用转换器将返回值写入响应体((HttpMessageConverter<T>) converter).write(value, contentType, new ServletServerHttpResponse(response));return;}}// 4. 如果没有找到支持的转换器,抛出异常throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
}
3.2 MappingJackson2HttpMessageConverter
的 write
方法
以 JSON 数据为例,MappingJackson2HttpMessageConverter
会将 Java 对象转换为 JSON 字符串并写入响应体。
public class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {@Overrideprotected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException {// 使用 Jackson 的 ObjectMapper 将对象转换为 JSON 字符串objectMapper.writeValue(outputMessage.getBody(), object);}
}
4. 响应体的写入流程
RequestMappingHandlerAdapter
调用目标方法后,获取返回值。RequestResponseBodyMethodProcessor
判断方法是否带有@ResponseBody
注解。- 如果带有
@ResponseBody
注解,则使用HttpMessageConverter
将返回值转换为响应体内容。 - 将转换后的内容写入
HttpServletResponse
的响应体中。 - 标记请求已处理,跳过视图渲染。
5. 总结:@ResponseBody
的处理流程
DispatcherServlet
接收到请求后,调用RequestMappingHandlerAdapter
。RequestMappingHandlerAdapter
使用RequestResponseBodyMethodProcessor
处理@ResponseBody
注解的返回值。RequestResponseBodyMethodProcessor
使用HttpMessageConverter
将返回值转换为响应体内容。- 将转换后的内容写入
HttpServletResponse
的响应体中。 - 标记请求已处理,跳过视图渲染。
通过以上流程,Spring MVC 能够将方法的返回值直接写入 HTTP 响应体中,从而实现 RESTful 风格的 API 开发。