最近工作对接接口出入参均是Xml,因此使用了jaxb来处理
首先先添加依赖:
<!--jaxb-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.5</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.5</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
工具类:对象转xml与xml转对象
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
public class XmlUtil {
// obj需要转换的对象 flag生成xml是否添加头信息
public static String objToXml(Object obj, boolean flag) {
// 创建输出流
StringWriter sw = new StringWriter();
try {
// 利用jdk中自带的转换类实现
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
// 格式化xml输出的格式
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
//是否省略xml头信息,默认不省略(false)
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, flag);
// 将对象转换成输出流形式的xml
marshaller.marshal(obj, sw);
} catch (JAXBException e) {
e.printStackTrace();
}
return sw.toString();
}
public static <T> T xmlToJson(String xml, Class<T> classType) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(classType);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (T) unmarshaller.unmarshal(new StringReader(xml));
}
public static Object convertXmlStrToObject(Class clazz, String xmlStr) {
Object xmlObject = null;
try {
JAXBContext context = JAXBContext.newInstance(clazz);
// 进行将Xml转成对象的核心接口
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader sr = new StringReader(xmlStr);
xmlObject = unmarshaller.unmarshal(sr);
} catch (JAXBException e) {
e.printStackTrace();
}
return xmlObject;
}
}
目标入参例子:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Xml>
<Head>
<Version>xxx</Version>
<SecurityMode>xxx</SecurityMode>
<CheckSum>xxx</CheckSum>
<From>xxx</From>
<To>xxx</To>
<ChannelCode>xxx</ChannelCode>
<Customer>xxx</Customer>
<PoolId>xxx</PoolId>
<DataFormat>xxx</DataFormat>
<MessageId>xxx</MessageId>
<MessageTime>xxx</MessageTime>
</Head>
<Request>
<ApiName>xxx</ApiName>
<ClientIP>xxx</ClientIP>
<Parameters>
<Field>xxx</Field>
</Parameters>
</Request>
</Xml>
当前需求如上所示,Head部分是不变的,ApiName内容决定调用哪个接口,
Parameters中对应各个接口需要的参数,但不同接口Parameters里面Field标签是不一样的,如果把所有字段都放一个对象里虽然也能实现功能,但看起来不够雅观,当前采用泛型,但Parameters标签是不变的,因此拼接xml时需要做些调整。
首先是最外层Xml标签:
@Data
@XmlRootElement(name = "Xml")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({SectionOfficeRequest.class, ScheduleRequest.class, ExpertRequest.class, PeriodRequest.class, BookingRequest.class, CancelBookingRequest.class})
@XmlType(propOrder = {"headBO", "requestBO", "responseVO"})
public class XmlBO<T> {
@XmlElement(name = "Head")
private HeadBO headBO;
@XmlAnyElement(lax = true)
private RequestBO<T> requestBO;
@XmlElement(name = "Response")
private ResponseVO responseVO;
}
@Data 作用是当前用到了其生成get、set方法
@XmlRootElement 作用是最外层标签是叫xml
@XmlElement 注解加到get方法标明下一节点名称
@XmlAccessorType(XmlAccessType.FIELD) 作用是可以使@XmlElement注解不用加get方法上,简化代码
@XmlSeeAlso、@XmlAnyElement(lax = true) 配套使用,确定泛型可传类型
@XmlType 生成xml顺序
@Data
@XmlRootElement(name = "Head")
@XmlAccessorType(XmlAccessType.FIELD)
public class HeadBO {
@XmlElement(name = "Version")
private String version;
@XmlElement(name = "SecurityMode")
private String securityMode;
...
}
未完待续…