@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 开发。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具