接口響應(yīng)以XML數(shù)據(jù)格式輸出,這些方法你都知道嗎?
環(huán)境:SpringBoot3.1.7 + JDK17
1. 簡(jiǎn)介
XML與JSON都是用于數(shù)據(jù)交換的格式,但它們之間存在一些關(guān)鍵差異,決定了何時(shí)應(yīng)該使用XML而不是JSON,以及何時(shí)應(yīng)該使用JSON而不是XML?一般會(huì)從如下幾方面考慮使用哪種數(shù)據(jù)格式:
可讀性:XML 文檔具有更好的可讀性,因?yàn)樗鼈兪褂妙?lèi)似于HTML的標(biāo)簽結(jié)構(gòu)。這對(duì)于需要人工解析和編輯的文檔特別有用。而JSON文檔的鍵值對(duì)結(jié)構(gòu)更緊湊,但在可讀性方面可能不如XML。
標(biāo)準(zhǔn)化和互操作性:XML 有一個(gè)強(qiáng)大的標(biāo)準(zhǔn)體系,包括 XML Schema、XSLT、XPath 等,這使得 XML 在跨平臺(tái)、跨語(yǔ)言的數(shù)據(jù)交換中非常受歡迎。而JSON雖然也有一些標(biāo)準(zhǔn)(如JSON Schema),但其普及度和成熟度不如XML。
數(shù)據(jù)綁定和模式:XML 支持將數(shù)據(jù)結(jié)構(gòu)與標(biāo)記語(yǔ)言(如 HTML)結(jié)合使用,這使得 XML 非常適合用于數(shù)據(jù)綁定。而JSON更傾向于簡(jiǎn)單的鍵值對(duì)結(jié)構(gòu),沒(méi)有這種數(shù)據(jù)綁定功能。
數(shù)據(jù)類(lèi)型:XML 支持內(nèi)置的數(shù)據(jù)類(lèi)型(如整數(shù)、布爾值等),這有助于更準(zhǔn)確地表示數(shù)據(jù)。而JSON的數(shù)據(jù)類(lèi)型系統(tǒng)更為簡(jiǎn)單,只支持基本的數(shù)據(jù)類(lèi)型和數(shù)組。
而如今采樣X(jué)ML格式進(jìn)行輸出的已經(jīng)非常少了,不過(guò)像銀行這樣的系統(tǒng)還是非常多的,最近做的一個(gè)項(xiàng)目與農(nóng)行對(duì)接他們的接口就是采用XML進(jìn)行數(shù)據(jù)交換(真麻煩啊,不過(guò)還好之前了解過(guò)JAXB)。
接下來(lái)我們通過(guò)實(shí)例講解在SpringBoot中如何控制輸出XML數(shù)據(jù)格式
2. 實(shí)戰(zhàn)案例
2.1 通過(guò)jackson
首先需要在項(xiàng)目中引入jackson xml依賴(lài)包
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
隨意定義數(shù)據(jù)模型
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("標(biāo)題", "內(nèi)容") ;
}
}
訪問(wèn)接口
圖片
輸出了XML,是不是覺(jué)得非常奇怪,就引入了xml依賴(lài)什么配置都沒(méi)有就輸出了XML數(shù)據(jù)格式。這是由于在容器在初始化HttpMessageConverter消息轉(zhuǎn)換器時(shí)有判斷,如果存在XML相關(guān)的轉(zhuǎn)換起就會(huì)加入到其中。
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()));
}
}
}
而上面的類(lèi)方法的調(diào)用是初始化HttpMessageConverters時(shí)創(chuàng)建
public class HttpMessageConvertersAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters)
// 在該構(gòu)造方法中調(diào)用上面的方法初始化默認(rèn)的轉(zhuǎn)換器
return new HttpMessageConverters(converters.orderedStream().toList()) ;
}
}
這里是一個(gè)過(guò)程,其實(shí)本身MappingJackson2XmlHttpMessageConverter也被定義為bean對(duì)象了。
protected static class MappingJackson2XmlHttpMessageConverterConfiguration {
@Bean
@ConditionalOnMissingBean
public MappingJackson2XmlHttpMessageConverter mappingJackson2XmlHttpMessageConverter(
Jackson2ObjectMapperBuilder builder) {
return new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build());
}
}
自定義XML的標(biāo)簽名稱(chēng)
@JacksonXmlRootElement(localName = "msg")
public class Message {
private String title ;
@JacksonXmlProperty(localName = "body")
private String content ;
}
輸出如下
圖片
而對(duì)于上面的接口,我們可以通過(guò)Accept請(qǐng)求header控制輸出的消息格式
圖片
2.2 使用Xml視圖技術(shù)
@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 ;
}
}
數(shù)據(jù)模型定義
@XmlRootElement(name = "user")
public class User {
private Integer age ;
private String name ;
private String sex ;
}
輸出如下
2.3 使用JAXB技術(shù)
@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需要引入如下依賴(lài)包:
<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>
以上就是有關(guān)輸出XML的所有內(nèi)容,希望本文對(duì)你有所幫助。
完畢?。?!