一、关于JAXB
JAXB是干什么的?
JAXB可以实现xml格式与对象之间的相互转换
JAXB相关知识点
1、JABX相关的类
- XmlType类:用于绑定java实体与XML之间的信息
- Marshaller接口:将Java实体序列化为XML数据
- Unmarshaller接口:将XML数据反序列化为Java对象
java实体与XML之间的相互转换最重要的就是后面两个接口。
2、JAXB相关注解
- @XmlType
- @XmlAccessorType
- @XmlAccessOrder
- @XmlJavaTypeAdapter
- @XmlElementWrapper
- @XmlRootElement
- @XmlElement
- @XmlAttribute
具体的用法可以借鉴一下【1】、【2】
比较常用的是
@XmlRootElement
@XmlElement
@XmlAccessType(XmlAccessType.FIELD)/(XmlAccessType.NONE)
@XmlElementWrapper
二、通过JAXB将java对象转化为xml格式(字符串)
util类(通用)
/**
* 将对象直接转换成String类型的 XML输出
*
* @param obj
* @return
*/
public static String convertToXml(Object obj, boolean formatted) {
// 创建输出流
StringWriter sw = new StringWriter();
try {
// 利用jdk中自带的转换类实现
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
// 格式化xml输出的格式
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, formatted);
//设置encoding为utf-16(默认utf-8)
// marshaller.setProperty(Marshaller.JAXB_ENCODING,"UTF-16");
//修改xml报文头
//隐去报文头的生成
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
//自定义生成报文头
sw.write("<?xml version=\"1.0\" encoding=\"utf-16\"?>\n");
// 将对象转换成输出流形式的xml
marshaller.marshal(obj, sw);
} catch (JAXBException e) {
e.printStackTrace();
}
return sw.toString();
}
java对象
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "info")
public class OrderListDataDTO implements Serializable {
private static final long serialVersionUID = -6669401393597013310L;
@XmlElement(name = "number")
private Integer number;
@XmlElement(name = "message")
private List<OrderListMessageDataDTO> messages;
}
要转化成下面xml格式
<soap:Envelope xmlns:soap=\"http://****/\" xmlns:xsd=\"http://****\" xmlns:xsi=\"http://****\"><soap:Body><ns1:findDealOrderInfoByUserIdResponse xmlns:ns1=\"http://****\"><ns1:out><?xml version='1.0' encoding='UTF-8'?><info><number>1</number><message orderId =\"01\" distId=\"05\" ></message></info></ns1:out></ns1:findDealOrderInfoByUserIdResponse></soap:Body></soap:Envelope>
转化代码
CreateDTO createDTO = new CreateDTO();
createDTO.setOrderInfoXml(XmlAndObjectUtils.convertToXml(orderListDataDTO , false));
XmlSoapEnvelopBodyDTO<CreateDTO> soapBody = XmlSoapEnvelopBodyDTO.build(createDTO);
String requestDataXml = XmlAndObjectUtils.convertToXml(soapBody, true);
createDTO.java
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "createOrder")
public class CreateDTO {
@XmlAttribute
private String xmlns = "http://***.com";
private String orderInfoXml;
}
@Data
@XmlRootElement(name = "soap:Envelope")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({CreateDTO.class})
public class XmlSoapEnvelopBodyDTO<T> {
@XmlAttribute(name = "xmlns:soap")
private String soap = "http://****/";
@XmlAttribute(name = "xmlns:xsi")
private String xsi = "http://****";
@XmlAttribute(name = "xmlns:xsd")
private String xsd = "http://****";
@XmlElement(name = "soap:Body")
private SoapBody<T> body;
public T getData() {
return body.getData();
}
public static <T> XmlSoapEnvelopBodyDTO<T> build(T data) {
XmlSoapEnvelopBodyDTO<T> b = new XmlSoapEnvelopBodyDTO<>();
b.setBody(new SoapBody<>());
b.body.setData(data);
return b;
}
@Data
@XmlAccessorType(XmlAccessType.FIELD)
private static class SoapBody<T> {
@XmlAnyElement(lax = true)
private T data;
}
}
三、通过JAXB将xml字符串转化为java对象
要转化的xml,可以复制去网上的xml格式化工具格式化一下
<soap:Envelope xmlns:soap=\"http://****" xmlns:xsd=\"http://****" xmlns:xsi=\"http://****"><soap:Body><ns1:create xmlns:ns1=\"http://****"><ns1:out><?xml version='1.0' encoding='UTF-8'?><info><flag>0</flag><message>成功</message></info></ns1:out></ns1:createOrderResponse></soap:Body></soap:Envelope>";
转化后的java对象如下:
public class result{
private Integer flag;
private String message;
}
开始整起
介绍一下util类(通用),可以直接拿去使用
/**
* 将XML转换为java对象
* @param xml
* @return
*/
public static DealOrderXmlDTO xmlToObject(String xml){
if (xml.equals("")){
return null;
}
DealOrderXmlDTO dto = null;
JAXBContext context = null;
try {
context = JAXBContext.newInstance(DealOrderXmlDTO.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
dto = (DealOrderXmlDTO)unmarshaller.unmarshal(new StringReader(xml));
} catch (JAXBException e) {
e.printStackTrace();
}
return dto;
}
xml最外层包装类
@Data
@XmlRootElement(name = "soap:Envelope")
@XmlAccessorType(XmlAccessType.FIELD)
//xml转对象:CreateResponseBodyDTO.class
@XmlSeeAlso({CreateResponseBodyDTO.class})
public class XmlSoapEnvelopBodyDTO<T> {
@XmlAttribute(name = "xmlns:soap")
private String soap = "http://****";
@XmlAttribute(name = "xmlns:xsi")
private String xsi = "http://****";
@XmlAttribute(name = "xmlns:xsd")
private String xsd = "http://****";
@XmlElement(name = "soap:Body")
private SoapBody<T> body;
public T getData() {
return body.getData();
}
public static <T> XmlSoapEnvelopBodyDTO<T> build(T data) {
XmlSoapEnvelopBodyDTO<T> b = new XmlSoapEnvelopBodyDTO<>();
b.setBody(new SoapBody<>());
b.body.setData(data);
return b;
}
@Data
@XmlAccessorType(XmlAccessType.FIELD)
private static class SoapBody<T> {
@XmlAnyElement(lax = true)
private T data;
}
}
xml次层包装类-body
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ns1:create")
public class CreateResponseBodyDTO {
@XmlAttribute(name = "xmlns:ns1")
private String ns1;
@XmlElement(name = "ns1:out")
private String out;
}
真正的实体类
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "info")
public class Result {
private Integer flag;
private String message;
}
转化的代码
//通过两次转化
XmlSoapEnvelopBodyDTO<CreateResponseBodyDTO> b = XmlAndObjectUtils.xmlToObject(resultXml, XmlSoapEnvelopBodyDTO.class);
XmlAndObjectUtils.xmlToObject(b.getData().getOut(), CreateResultDataDTO.class);
四、补充
当java对象转化为xml时,若对象的某个字段值为null,则会导致生成的xml不会出现对象的标签,目前为止,还没有找到比较好的解决办法,网上也只是说在定义该字段时,给一个默认值(如:“”)。若还有更好的解决办法,欢迎在评论区解答。