jackson解析xml文件或xml格式请求以及踩坑经历
最近写的接口要被外部接口调用,请求格式为xml,在网上搜索,有的是用代码去解析的例如 使用HttpServletRequest.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
StringBuffer xml = new StringBuffer();
while ((buffer = br.readLine()) != null) {
// 在页面中显示读取到的请求参数
xml.append(buffer);} 使用流的方式解析成String,再通过Document.getRootElement()获得节点
参考:https://blog.csdn.net/myme95/article/details/94454324
但是后来发现jackson提供了方便的注解
步骤1:引入依赖
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
步骤2:在controller的方法注解上表明是xml格式
@PostMapping(value = "", produces = {MediaType.APPLICATION_XML_VALUE}, consumes = {MediaType.APPLICATION_XML_VALUE})
ResponseData<Integer> createCustomer(@RequestBody @Valid TestReqDto reqDto);
步骤3:在请求dto上表明注解 @JacksonXmlRootElement表示根节点,@JacksonXmlElementWrapper表示集合@JacksonXmlProperty表明解析的注解名称,如果dto的name属性和标签的名称是一样的,那么可以省略
比如解析的xml格式如下
<date>
<bb>bbbbbb</bb>
<students>
<student>
<name>111</name>
<age>234</age>
</student>
<student>
<name>222</name>
<age>245</age>
</student>
</students>
</date>
对应是实体类写法
@Data
@ApiModel(value = "车辆列表请求Dto")
@JacksonXmlRootElement(localName = "date")
public class TestReqDto {
@JacksonXmlProperty(localName = "student")
@JacksonXmlElementWrapper(localName = "students")
private List<TestAA> aa;
//@JacksonXmlProperty(localName = "bb")
private String bb;
}
@Data
@ApiModel(value = "TestAA")
public class TestAA {
//@JacksonXmlProperty(localName = "name")
private String name;
//@JacksonXmlProperty(localName = "age")
private String age;
}
注意事项
1.测试的时候xml格式要写正确,粗心的我一开始写成了<name><name/> 并且xml文件是已<?xml version="1.0" encoding="UTF-8"?>为第一行的,使用swagger测试 要加上
2.引入jackson的依赖后,导致所有接口的返回格式都变成了xml.这是因为引入依赖后,虽然application/json和application/xml是相等的,但由于这个排序是稳定排序(相等值顺序不变),而且application/xml的记载顺序更先,因此总是选中了application/xml。解决方式:设置默认contentType, 通过 implements WebMvcconfigurer
@Configuration
public class WebInterceptorAdapter implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON, MediaType.TEXT_XML, MediaType.APPLICATION_XML);
}
}