@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 {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
// 判断方法是否带有 @ResponseBody 注解
return returnType.hasMethodAnnotation(ResponseBody.class);
}
@Override
public 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 {
@Override
protected 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 开发。

浙公网安备 33010602011771号