接口响应以XML数据格式输出,这些方法你都知道吗?

开发 前端
XML与JSON都是用于数据交换的格式,但它们之间存在一些关键差异,决定了何时应该使用XML而不是JSON,以及何时应该使用JSON而不是XML?

环境:SpringBoot3.1.7 + JDK17

1. 简介

XML与JSON都是用于数据交换的格式,但它们之间存在一些关键差异,决定了何时应该使用XML而不是JSON,以及何时应该使用JSON而不是XML?一般会从如下几方面考虑使用哪种数据格式:

可读性:XML 文档具有更好的可读性,因为它们使用类似于HTML的标签结构。这对于需要人工解析和编辑的文档特别有用。而JSON文档的键值对结构更紧凑,但在可读性方面可能不如XML。

标准化和互操作性:XML 有一个强大的标准体系,包括 XML Schema、XSLT、XPath 等,这使得 XML 在跨平台、跨语言的数据交换中非常受欢迎。而JSON虽然也有一些标准(如JSON Schema),但其普及度和成熟度不如XML。

数据绑定和模式:XML 支持将数据结构与标记语言(如 HTML)结合使用,这使得 XML 非常适合用于数据绑定。而JSON更倾向于简单的键值对结构,没有这种数据绑定功能。

数据类型:XML 支持内置的数据类型(如整数、布尔值等),这有助于更准确地表示数据。而JSON的数据类型系统更为简单,只支持基本的数据类型和数组。

而如今采样XML格式进行输出的已经非常少了,不过像银行这样的系统还是非常多的,最近做的一个项目与农行对接他们的接口就是采用XML进行数据交换(真麻烦啊,不过还好之前了解过JAXB)。

接下来我们通过实例讲解在SpringBoot中如何控制输出XML数据格式

2. 实战案例

2.1 通过jackson

首先需要在项目中引入jackson xml依赖包

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

随意定义数据模型

public class Message {
  private String title ;
  private String content ;
}

Controller接口

@RestController
@RequestMapping("/mfc")
public class MessageFormatController {
  
  @GetMapping(value = "/index")
  public Object index() {
    return new Message("标题", "内容") ;
  }
  
}

访问接口

图片图片

输出了XML,是不是觉得非常奇怪,就引入了xml依赖什么配置都没有就输出了XML数据格式。这是由于在容器在初始化HttpMessageConverter消息转换器时有判断,如果存在XML相关的转换起就会加入到其中。

public class WebMvcConfigurationSupport {
  private static final boolean jackson2XmlPresent;
  static {
    jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
  }
  protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
    if (jackson2XmlPresent) {
      Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
      if (this.applicationContext != null) {
        builder.applicationContext(this.applicationContext);
      }
      messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
    }
  }
}

而上面的类方法的调用是初始化HttpMessageConverters时创建

public class HttpMessageConvertersAutoConfiguration {
  @Bean
  @ConditionalOnMissingBean
  public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters)
    // 在该构造方法中调用上面的方法初始化默认的转换器
    return new HttpMessageConverters(converters.orderedStream().toList()) ;
  }
}

这里是一个过程,其实本身MappingJackson2XmlHttpMessageConverter也被定义为bean对象了。

protected static class MappingJackson2XmlHttpMessageConverterConfiguration {
  @Bean
  @ConditionalOnMissingBean
  public MappingJackson2XmlHttpMessageConverter mappingJackson2XmlHttpMessageConverter(
      Jackson2ObjectMapperBuilder builder) {
    return new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build());
  }
}

自定义XML的标签名称

@JacksonXmlRootElement(localName = "msg")
public class Message {
  private String title ;
  @JacksonXmlProperty(localName = "body")
  private String content ;
}

输出如下

图片图片

而对于上面的接口,我们可以通过Accept请求header控制输出的消息格式

图片图片

2.2 使用Xml视图技术

@RestController
@RequestMapping("/jaxb")
public class JaxbController {
  @GetMapping("/xml")
  public ModelAndView xml() {
    MappingJackson2XmlView view = new MappingJackson2XmlView() ;
    ModelAndView model = new ModelAndView(view) ;
    Map<String, Object> modelMap = new HashMap<>() ;
    modelMap.put("user", new User(66, "张三", "女")) ;
    modelMap.put("zs", new User(55, "李四", "男")) ;
    view.setModelKey("zs") ;
    model.addAllObjects(modelMap) ;
    return model ;
  }
}

数据模型定义

@XmlRootElement(name = "user")
public class User {
  private Integer age ;
  private String name ;
  private String sex ;
}

输出如下

2.3 使用JAXB技术

@GetMapping("/marshaller")
public MarshallingView marshaller() {
  Jaxb2Marshaller marshaller = new Jaxb2Marshaller() ;
  marshaller.setClassesToBeBound(User.class) ;
  MarshallingView view = new MarshallingView(marshaller) ;
  view.getAttributesMap().put("user", new User(22, "张三", "男")) ;
  return view ;
}

输出如下

图片

嵌套属性支持

@XmlRootElement(name = "user")
public class User {


  private Integer age ;
  private String name ;
  private String sex ;
  @XmlElement(name = "address")
  private Address address = new Address("四川", "成都") ;
  
}

输出

图片图片

以上基于JAXB需要引入如下依赖包:

<dependency>
  <groupId>jakarta.xml.bind</groupId>
  <artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-oxm</artifactId>
</dependency>

以上就是有关输出XML的所有内容,希望本文对你有所帮助。

完毕!!!

责任编辑:武晓燕 来源: Spring全家桶实战案例源码
相关推荐

2024-04-28 08:20:52

Controller接口URL

2021-08-05 18:21:29

Autowired代码spring

2016-01-11 09:48:07

2018-08-07 09:29:35

数据库MySQL优化方法

2019-07-08 10:18:38

MPLSIP数据

2019-02-12 11:15:15

Spring设计模式Java

2016-03-18 19:03:35

认知计算IBM

2022-11-10 09:00:41

2015-07-03 11:20:41

编程学习方法

2021-07-29 06:55:03

Spring@AutowriedbyType注入

2022-09-07 09:01:14

JS操作符运算符

2020-05-27 11:30:54

Chrome DevT前端命令

2024-03-26 10:10:45

JavaScript操作符操作表达式

2023-02-15 08:12:19

http超时过滤器

2021-04-10 07:04:00

WPS技巧办公软件

2020-10-28 11:20:55

vue项目技

2018-02-06 09:06:03

主流分布式存储系统

2020-02-20 08:30:49

OSPF网络协议路由协议

2023-02-01 08:31:36

JavaScript循环遍历

2018-05-15 08:27:20

Scikit-lear机器学习Python
点赞
收藏

51CTO技术栈公众号