關(guān)于@ResponseBody 默認(rèn)輸出的誤區(qū)的解答
背景
@ResponseBody 默認(rèn)情況返回的數(shù)據(jù)格式是什么?所謂默認(rèn)情況 后臺接口不指定 produces MediaType
@Controller
public class DemoController {
@ResponseBody
@GetMapping(value = "/demo")
public DemoVO demo() {
return new DemoVO("lengleng", "123456");
}
}
使用百度搜索 @ResponseBody 排名第一的答案, @ResponseBody 的作用其實(shí)是將 java 對象轉(zhuǎn)為 json 格式的數(shù)據(jù)。

正確答案
我們先來公布正確的答案。
@ResponseBody 的輸出格式,默認(rèn)情況取決于客戶端的 Accept 請求頭。


源碼剖析
RequestResponseBodyMethodProcessor
public class RequestResponseBodyMethodProcessor {
// 處理 ResponseBody 標(biāo)注的方法
@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) {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// 處理返回值
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
}
writeWithMessageConverters
protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) {
HttpServletRequest request = inputMessage.getServletRequest();
// 獲取請求頭中的目標(biāo)資源類型
List<MediaType> acceptableTypes = getAcceptableMediaTypes(request);
// 獲取接口指定支持的資源類型
List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType);
// 獲取能夠輸出資源類型
List<MediaType> mediaTypesToUse = new ArrayList<>();
for (MediaType requestedType : acceptableTypes) {
for (MediaType producibleType : producibleTypes) {
if (requestedType.isCompatibleWith(producibleType)) {
mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));
}
}
}
/// 排序
MediaType.sortBySpecificityAndQuality(mediaTypesToUse);
for (MediaType mediaType : mediaTypesToUse) {
// 判斷資源類型是否是具體的類型,而不是帶通配符 * 這種
if (mediaType.isConcrete()) {
selectedMediaType = mediaType;
break;
}
else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
break;
}
}
selectedMediaType = selectedMediaType.removeQualityValue();
// 查找支持選中資源類型的 HttpMessageConverter,輸出body
for (HttpMessageConverter<?> converter : this.messageConverters) {
GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?
(GenericHttpMessageConverter<?>) converter : null);
if (genericConverter != null ?
((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :
converter.canWrite(valueType, selectedMediaType)) {
body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,
(Class<? extends HttpMessageConverter<?>>) converter.getClass(),
inputMessage, outputMessage);
return;
}
}
}
為什么我要去研究這個(gè)問題
當(dāng)升級至 spring cloud alibaba 2.2.1 時(shí), sentinel 模塊 引入以下依賴

當(dāng)依賴中出現(xiàn) dataformat jar 時(shí)候, RestTemplate ,會在默認(rèn) Accept 請求頭增加
application/xml | text/xml | application/*+xml

public MappingJackson2XmlHttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, new MediaType("application", "xml", StandardCharsets.UTF_8),
new MediaType("text", "xml", StandardCharsets.UTF_8),
new MediaType("application", "*+xml", StandardCharsets.UTF_8));
Assert.isInstanceOf(XmlMapper.class, objectMapper, "XmlMapper required");
}
當(dāng)我們使用 RestTemplate 調(diào)用接口時(shí)候,若不指定 Accept 會返回 XML ,導(dǎo)致不能平滑升級
到此這篇關(guān)于關(guān)于@ResponseBody 默認(rèn)輸出的誤區(qū)的解答的文章就介紹到這了,更多相關(guān)@ResponseBody 默認(rèn)輸出內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解SpringBoot中添加@ResponseBody注解會發(fā)生什么
- 詳解SpringBoot定制@ResponseBody注解返回的Json格式
- SpringBoot使用@ResponseBody返回圖片的實(shí)現(xiàn)
- 解決使用@ResponseBody后返回500錯(cuò)誤的問題
- spring boot @ResponseBody轉(zhuǎn)換JSON 時(shí) Date 類型處理方法【兩種方法】
- Springmvc 4.x利用@ResponseBody返回Json數(shù)據(jù)的方法
- spring+mybatis 通過@ResponseBody返回結(jié)果中文亂碼的解決方法
- springMvc注解之@ResponseBody和@RequestBody詳解
- SpringMVC中解決@ResponseBody注解返回中文亂碼問題
- @ResponseBody 和 @RequestBody 注解的區(qū)別
- SpringMVC注解之@ResponseBody注解原理
相關(guān)文章
java代碼實(shí)現(xiàn)C盤文件統(tǒng)計(jì)工具
今天周末,給大家分享基于java代碼實(shí)現(xiàn)C盤文件統(tǒng)計(jì)工具,在這小編使用的版本是Maven-3.9.9,jdk1.8,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-07-07
java serialVersionUID解決序列化類版本不一致問題面試精講
這篇文章主要為大家介紹了serialVersionUID解決序列化類版本不一致問題的面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
Java實(shí)現(xiàn)多個(gè)sheet頁數(shù)據(jù)導(dǎo)出功能
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多個(gè)sheet頁數(shù)據(jù)導(dǎo)出功能的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
詳解使用Maven構(gòu)建多模塊項(xiàng)目(圖文)
這篇文章主要介紹了詳解使用Maven構(gòu)建多模塊項(xiàng)目(圖文),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-09-09
Layui前后臺交互數(shù)據(jù)獲取java實(shí)例
下面小編就為大家分享一篇Layui前后臺交互數(shù)據(jù)獲取java實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01
Java實(shí)現(xiàn)訂單超時(shí)未支付自動(dòng)取消的8種方法總結(jié)
這篇文章主要為大家介紹了Java實(shí)現(xiàn)訂單超時(shí)未支付自動(dòng)取消功能的8種不同方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-08-08
Java實(shí)現(xiàn)學(xué)生管理系統(tǒng)(控制臺版本)
這篇文章主要為大家詳細(xì)介紹了如何利用Java語言實(shí)現(xiàn)控制臺版本的學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
Java中實(shí)現(xiàn)String.padLeft和String.padRight的示例
本篇文章主要介紹了Java中實(shí)現(xiàn)String.padLeft和String.padRight,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09

