本文从引入jackson-dataformat-xml 之后接口全变成xml 现象开始,一步步排查代码原因,并提出解决方案。希望能对遇到相关问题的人有所帮助

新调用上游一个接口,增加了对方的一个api包,没修改任何逻辑,接口却从json返回全变成了xml格式?
原接口:

现在:

排查之后定位到是因为对方的api包里增加了一个依赖包

<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>2.9.7</version>
</dependency>

那这个包是怎么生效的呢?
需要从spring-mvc 说起
当我们的代码里这么写的时候

spring-mvc 的执行流程:

SpringMVC执行流程:

1.用户发送请求至前端控制器DispatcherServlet
2.DispatcherServlet收到请求调用处理器映射器HandlerMapping。
3.处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。
4.DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作
5.执行处理器Handler(Controller,也叫页面控制器)。
6.Handler执行完成返回ModelAndView
7.HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet
8.DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9.ViewReslover解析后返回具体View
10.DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。
11.DispatcherServlet响应用户。

其中第9步骤里,ViewReslover解析后返回具体View 。
这里在找对应的解析器的时候有这样一步 第381行:

我们看到在getDefaultMediaTypes() 这里


就恍然大悟了。spring-webmvc里 已经有写好的判断是否有当前类 如果有作为一个可处理的类型放在map里,而恰好xml 在json之前

那么有什么办法 避免引入这个包之后就变成了xml么?如果能排除当然可以排除这个包,但是仍然无法避免下次其他依赖包里是否有对应的依赖,并且也无法排除你的项目里真的不会遇到这个包。那么怎么样可以避免呢?

其实答案就在上边的这个图里,看下方法 writeWithMessageConvert 的逻辑

protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType,  ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)  throws IOException, HttpMediaTypeNotAcceptableException {  Class<?> returnValueClass = returnValue.getClass();  HttpServletRequest servletRequest = inputMessage.getServletRequest();
//获取客户端Accept字段接收的content-type  List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(servletRequest);
//获取服务器端指定的content-type,如果@RequestMapping中的produces配置了content-type,则返回此content-type,若果没有,
则获取所有HttpMessageConverter所支持的content-type,然后通过requestedMediaTypes和producibleMediaTypes 对比,选定一个最合适的content-type作为
//selectedMediaType  List<MediaType> producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass);  Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();  for (MediaType requestedType : requestedMediaTypes) {  for (MediaType producibleType : producibleMediaTypes) {  if (requestedType.isCompatibleWith(producibleType)) {  compatibleMediaTypes.add(getMostSpecificMediaType(requestedType, producibleType));  }  }  }  if (compatibleMediaTypes.isEmpty()) {  throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes);  }  List<MediaType> mediaTypes = new ArrayList<MediaType>(compatibleMediaTypes);  MediaType.sortBySpecificityAndQuality(mediaTypes);  MediaType selectedMediaType = null;  for (MediaType mediaType : mediaTypes) {  if (mediaType.isConcrete()) {  selectedMediaType = mediaType;  break;  }  else if (mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) {  selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;  break;  }  }  if (selectedMediaType != null) {  selectedMediaType = selectedMediaType.removeQualityValue();  for (HttpMessageConverter<?> messageConverter :
//遍历所有已注册的HttpMessageConverter,选出一个支持返回值类型returnValueClass和
//selectedMediaType的HttpMessageConverter来进行写入数据到response的body中。
this.messageConverters) {  if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {  ((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage);  if (logger.isDebugEnabled()) {  logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" +  messageConverter + "]");  }  return;  }  }  }  throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);  }

所以 比较安全的解决办法是:
1) 提供方法时,我们可以指定方法的返回类型
例如: @RequestMapping(value ="/test",produces=“application/json”) 中 produces 可以指定方法对应的类型等

2) 请求方法时,我们可以指定想要的返回类型
例如:

源码解析-为什么引入了jackson-dataformat-xml 包我的接口全变成了xml格式?相关推荐

  1. SpringSession的源码解析(从Cookie中读取Sessionid,根据sessionid查询信息全流程分析)

    前言 上一篇我们介绍了SpringSession中Session的保存过程,今天我们接着来看看Session的读取过程.相对保存过程,读取过程相对比较简单. 本文想从源码的角度,详细介绍一下Sessi ...

  2. SpringBoot入门-源码解析(雷神)

    一.Spring Boot入门 视频学习资料(雷神): https://www.bilibili.com/video/BV19K4y1L7MT?p=1 github: https://github.c ...

  3. Spring源码深度解析(郝佳)-学习-源码解析-Spring MVC(三)-Controller 解析

    在之前的博客中Spring源码深度解析(郝佳)-学习-源码解析-Spring MVC(一),己经对 Spring MVC 的框架做了详细的分析,但是有一个问题,发现举的例子不常用,因为我们在实际开发项 ...

  4. python flask源码解析_用尽洪荒之力学习Flask源码

    [TOC] 一直想做源码阅读这件事,总感觉难度太高时间太少,可望不可见.最近正好时间充裕,决定试试做一下,并记录一下学习心得. 首先说明一下,本文研究的Flask版本是0.12. 首先做个小示例,在p ...

  5. Android源码解析(一)动画篇-- Animator属性动画系统

    Android源码解析-动画篇 Android源码解析(一)动画篇-- Animator属性动画系统 Android源码解析(二)动画篇-- ObjectAnimator Android在3.0版本中 ...

  6. [Android] Handler源码解析 (Java层)

    之前写过一篇文章,概述了Android应用程序消息处理机制.本文在此文基础上,在源码级别上展开进行概述 简单用例 Handler的使用方法如下所示: Handler myHandler = new H ...

  7. Redux 源码解析系列(一) -- Redux的实现思想

    文章来源: IMweb前端社区 黄qiong(imweb.io) IMweb团队正在招聘啦,简历发至jayccchen@tencent.com Redux 其实是用来帮我们管理状态的一个框架,它暴露给 ...

  8. clickhouse原理解析与开发实战 pdf_重识SSM,“超高频面试点+源码解析+实战PDF”,一次性干掉全拿走...

    重识SSM,"超高频面试点"+"源码解析"+"实战PDF",一次性干掉全拿走!! 01 超高频面试点知识篇 1.1 Spring超高频面试点 ...

  9. Java HashSet源码解析

    本解析源码来自JDK1.7,HashSet是基于HashMap实现的,方法实现大都直接调用HashMap的方法 另一篇HashMap的源码解析文章 概要 实现了Set接口,实际是靠HashMap实现的 ...

  10. usestate中的回调函数_React Hooks 源码解析(3):useState

    React 源码版本: v16.11.0 源码注释笔记: airingursb/react​github.com 在写本文之前,事先阅读了网上了一些文章,关于 Hooks 的源码解析要么过于浅显.要么 ...

最新文章

  1. 服务端关闭session的重要性
  2. LintCode 1.A+B的问题
  3. 层次聚类多维度matlab实现_第34集 python机器学习:凝聚聚类
  4. 2021全州高中高考成绩查询,最新!最全!桂林各中学高考成绩汇总!为桂林考生骄傲!...
  5. java的autotype,关于 fastjson 异常 autoType is not support 问题分析解决
  6. 这些大佬,真的牛逼了!
  7. iOS开发 - 动画实践系列
  8. 操作系统—死锁的检测和解除
  9. Klevgrand Tines for Mac(电钢琴模拟插件)
  10. Linux系统下架设PPTP ×××服务器
  11. Excel自定义格式详解
  12. USB Mass Storage大容量存储的基本知识
  13. 看懂英文数据手册、搭建电路
  14. 计算机专业需要盲打,计算机盲打的技巧与方法【听看打练习】
  15. 六、品达通用权限系统__pd-tools-log
  16. Cookie加密10
  17. 地壳中元素含量排名记忆口诀_地壳中元素含量_地壳中元素含量口诀
  18. 几何画板与运筹学作图注记
  19. 关于css的display:flex inline block inline-block和float
  20. mysql备份表语句

热门文章

  1. 计算机科学与技术的学士服是什么颜色的,学士服颜色分类 各色学士服都有什么讲究...
  2. R语言 正态性检验 Q-Q plot shapiro test
  3. 运维常用表格-干货分享
  4. Reflex WMS入门系列三十七:三种不同风格的RF界面
  5. 自抗扰控制器七-二阶 LADRC-PLL 结构设计
  6. oracle执行计划分析
  7. 972_MISRA C 2004规范解读1
  8. 数组转为集合的方法解析
  9. 液压传动与气动技术【1】
  10. YS-F4Pro开发板第四章:开发环境搭建【IAR和KEIL区别】【cube软件】【ST-Link和Jlink】