伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

关于@ResponseBody默认输出的误区

来源:本站原创 浏览:105次 时间:2022-10-10
背景
  • @ResponseBody 默认情况返回的数据格式是什么?所谓默认情况 后台接口不指定 produces MediaType
@Controller
public class DemoController {
 @ResponseBody
 @GetMapping(value = "/demo")
 public DemoVO demo() {
   return new DemoVO("lengleng", "123456");
 }
}
  • 使用百度搜索 @ResponseBody 排名第一的答案, @ResponseBody 的作用其实是将 java 对象转为 json 格式的数据。

正确答案

我们先来公布正确的答案。

@ResponseBody 的输出格式,默认情况取决于客户端的Accept 请求头。

源码剖析
  • RequestResponseBodyMethodProcessor
public class RequestResponseBodyMethodProcessor {
// 处理 ResponseBody 标注的方法
@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();
 // 获取请求头中的目标资源类型
 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;
   }
 }
}
为什么我要去研究这个问题
  • 当升级至 spring cloud alibaba 2.2.1 时, sentinel 模块 引入以下依赖

  • 当依赖中出现 dataformat jar 时候, RestTemplate ,会在默认 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");
}
  • 当我们使用 RestTemplate 调用接口时候,若不指定 Accept 会返回 XML ,导致不能平滑升级


  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net