一、简介
- 本文主要讲解JAXB来处理对象与XML进行互转。
- 其中关于CDATA数据的处理参考: Jaxb如何优雅的处理CData 这篇文章的实现,并略作改动。
二、常用注解(TODO)
三、封装
3.1 pom依赖(TODO)
3.2 CDataAdapter
package com.zhenai.sweet.qywx.provider.util;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/**
* JAXB的CDATA转换处理类
*/
public class CDataAdapter extends XmlAdapter<String, String> {
@Override
public String unmarshal(String v) throws Exception {
return v;
}
@Override
public String marshal(String v) throws Exception {
return new StringBuilder("<![CDATA[").append(v).append("]]>").toString();
}
}
3.3 CDataHandler
package com.zhenai.sweet.qywx.provider.util;
import javax.xml.stream.XMLStreamWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理处理
*/
public class CDataHandler implements InvocationHandler {
private XMLStreamWriter writer;
public CDataHandler(XMLStreamWriter writer) {
this.writer = writer;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method gWriteCharactersMethod = null;
try {
gWriteCharactersMethod = XMLStreamWriter.class.getDeclaredMethod("writeCharacters", String.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
if (gWriteCharactersMethod.equals(method)) {
String text = (String) args[0];
if (text != null && text.startsWith("<![CDATA[") && text.endsWith("]]>")) {
writer.writeCData(text.substring(9, text.length() - 3));
return null;
}
}
return method.invoke(writer, args);
}
}
3.4 JaxbXmlUtil
package com.zhenai.sweet.qywx.provider.util;
import lombok.extern.slf4j.Slf4j;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
/**
* @Description Jaxb工具类 xml和java类相互转换
* @Author: qjwyss
* @Date: 2020/3/13 16:59
* @Version V1.0
*/
@Slf4j
public class JaxbXmlUtil {
private static final String DEFAULT_ENCODING = "UTF-8";
/**
* pojo转换成xml 默认编码UTF-8
*
* @param obj 待转化的对象
* @return xml格式字符串
* @throws Exception JAXBException
*/
public static String pojo2xml(Object obj) throws Exception {
return pojo2xml(obj, DEFAULT_ENCODING);
}
/**
* pojo转换成xml
*
* @param obj 待转化的对象
* @param encoding 编码
* @return xml格式字符串
* @throws Exception JAXBException
*/
public static String pojo2xml(Object obj, String encoding) throws Exception {
String result = null;
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
// 指定是否使用换行和缩排对已编组 XML 数据进行格式化的属性名称。
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
try (StringWriter writer = new StringWriter();) {
XMLStreamWriter streamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
XMLStreamWriter cdataStreamWriter = (XMLStreamWriter) Proxy.newProxyInstance(
streamWriter.getClass().getClassLoader(),
streamWriter.getClass().getInterfaces(),
new CDataHandler(streamWriter)
);
marshaller.marshal(obj, cdataStreamWriter);
result = formatXml(writer.toString());
} catch (Exception e) {
log.error("读取数据失败", e);
}
return result;
}
/**
* xml转换成pojo
*
* @param xml xml格式字符串
* @param t 待转化的对象
* @return 转化后的对象
* @throws Exception JAXBException
*/
@SuppressWarnings("unchecked")
public static <T> T xml2pojo(String xml, Class<T> t) throws Exception {
T obj;
JAXBContext context = JAXBContext.newInstance(t);
Unmarshaller unmarshaller = context.createUnmarshaller();
try (StringReader stringReader = new StringReader(xml)) {
obj = (T) unmarshaller.unmarshal(stringReader);
}
return obj;
}
/**
* xml文本对齐
*/
private static String formatXml(String xml) {
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
// 打开对齐开关
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// 忽略掉xml声明头信息
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
StringWriter formattedStringWriter = new StringWriter();
transformer.transform(new StreamSource(new StringReader(xml)),
new StreamResult(formattedStringWriter));
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ formattedStringWriter.toString();
} catch (TransformerException e) {
}
return null;
}
}
四、使用
4.1 简单对象互转
4.1.0 说明
- 此处仅使用一个简单User对象来进行转换;
4.1.1 User对象
package com.zhenai.sweet.qywx.provider.util;
import lombok.Data;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "user")
@XmlType(propOrder = {
"uid",
"username",
"password"
})
public class User implements Serializable {
private static final long serialVersionUID = -4476533660865890728L;
private Long uid;
private String username;
private String password;
@XmlAttribute
private String gender;
public User() {
}
public User(Long uid, String username, String password, String gender) {
this.uid = uid;
this.username = username;
this.password = password;
this.gender = gender;
}
}
4.1.2 使用
// 简单对象互转
User user = new User(1L, "小明", "123456", "男");
String userXml = JaxbXmlUtil.pojo2xml(user);
log.info("简单对象转换XML结果: {}", userXml);
user = JaxbXmlUtil.xml2pojo(userXml, User.class);
log.info("简单XML转换对象结果: {}", user.toString());
4.1.3 结果
19:31:57.023 [main] INFO com.zhenai.sweet.qywx.provider.util.JaxbXmlUtil - 简单对象转换XML结果: <?xml version="1.0" encoding="UTF-8"?>
<user gender="男">
<uid>1</uid>
<username>小明</username>
<password>123456</password>
</user>
19:31:57.035 [main] INFO com.zhenai.sweet.qywx.provider.util.JaxbXmlUtil - 简单XML转换对象结果: User(uid=1, username=小明, password=123456, gender=男)
4.2 复杂对象互转
4.2.0 说明
- 此处通过设置嵌套对象来转换复杂的xml
- 有三个对象,班级对象,老师对象,学生对象; 一个班级对应一个老师,一个班级对应一群学生;
4.2.1 对象
package com.zhenai.sweet.qywx.provider.util;
import lombok.Data;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
import java.util.List;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "banji")
@XmlType(propOrder = {
"classId",
"className",
"teacher",
"studentList"
})
public class Banji implements Serializable {
private static final long serialVersionUID = -7645165684680423691L;
private Long classId;
private String className;
private Teacher teacher;
@XmlElementWrapper
@XmlElement(name = "student")
private List<Student> studentList;
public Banji() {
}
public Banji(Long classId, String className, Teacher teacher, List<Student> studentList) {
this.classId = classId;
this.className = className;
this.teacher = teacher;
this.studentList = studentList;
}
}
package com.zhenai.sweet.qywx.provider.util;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.io.Serializable;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "teacher")
@XmlType(propOrder = {
"teacherName",
"teacherGender",
})
public class Teacher implements Serializable {
private static final long serialVersionUID = 9190597564351664551L;
private String teacherName;
private String teacherGender;
public Teacher() {
}
public Teacher(String teacherName, String teacherGender) {
this.teacherName = teacherName;
this.teacherGender = teacherGender;
}
}
package com.zhenai.sweet.qywx.provider.util;
import lombok.Data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.io.Serializable;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "student")
@XmlType(propOrder = {
"studentName",
"age",
})
public class Student implements Serializable {
private static final long serialVersionUID = -7099299365239347614L;
private String studentName;
private Integer age;
public Student() {
}
public Student(String studentName, Integer age) {
this.studentName = studentName;
this.age = age;
}
}
4.2.2 使用
// 复合对象互转
Teacher teacher = new Teacher("语文老师", "女");
List<Student> studentList = new ArrayList<>();
Student student1 = new Student("小雪", 15);
Student student2 = new Student("小花", 13);
Student student3 = new Student("小李", 14);
studentList.add(student1);
studentList.add(student2);
studentList.add(student3);
Banji banji = new Banji(2L, "三年一班", teacher, studentList);
String banjiXml = JaxbXmlUtil.pojo2xml(banji);
log.info("复合对象转XML:{}", banjiXml);
banji = JaxbXmlUtil.xml2pojo(banjiXml, Banji.class);
log.info("复合XML转对象结果:{}", banji.toString());
4.2.3 结果
19:35:42.168 [main] INFO com.zhenai.sweet.qywx.provider.util.JaxbXmlUtil - 复合对象转XML:<?xml version="1.0" encoding="UTF-8"?>
<banji>
<classId>2</classId>
<className>三年一班</className>
<teacher>
<teacherName>语文老师</teacherName>
<teacherGender>女</teacherGender>
</teacher>
<studentList>
<student>
<studentName>小雪</studentName>
<age>15</age>
</student>
<student>
<studentName>小花</studentName>
<age>13</age>
</student>
<student>
<studentName>小李</studentName>
<age>14</age>
</student>
</studentList>
</banji>
19:35:42.171 [main] INFO com.zhenai.sweet.qywx.provider.util.JaxbXmlUtil - 复合XML转对象结果:Banji(classId=2, className=三年一班, teacher=Teacher(teacherName=语文老师, teacherGender=女), studentList=[Student(studentName=小雪, age=15), Student(studentName=小花, age=13), Student(studentName=小李, age=14)])
4.3 CDATA使用
4.3.0 说明
- 仅需要在需要CDATA的字段上加上注解@XmlJavaTypeAdapter(CDataAdapter.class)即可;
4.3.1 User对象
package com.zhenai.sweet.qywx.provider.util;
import lombok.Data;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.Serializable;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "user")
@XmlType(propOrder = {
"uid",
"username",
"password"
})
public class User implements Serializable {
private static final long serialVersionUID = -4476533660865890728L;
private Long uid;
@XmlJavaTypeAdapter(CDataAdapter.class)
private String username;
private String password;
@XmlAttribute
private String gender;
public User() {
}
public User(Long uid, String username, String password, String gender) {
this.uid = uid;
this.username = username;
this.password = password;
this.gender = gender;
}
}
4.3.2 结果
19:40:34.177 [main] INFO com.zhenai.sweet.qywx.provider.util.JaxbXmlUtil - 简单对象转换XML结果: <?xml version="1.0" encoding="UTF-8"?>
<user gender="男">
<uid>1</uid>
<username><![CDATA[小明]]></username>
<password>123456</password>
</user>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/17690.html