不安分的黑娃
踏踏实实,坚持学习,慢慢就懂了~

JAXB 使用记录

参考资料

什么是 JAXB ?

开源中国:

JAXB(Java Architecture for XML Binding简称JAXB)允许Java开发人员将Java类映射为XML表示方式。JAXB提供两种主要特性:将一个Java对象序列化为XML,以及反向操作,将XML解析成Java对象。换句话说,JAXB允许以XML格式存储和读取数据,而不需要程序的类结构实现特定的读取XML和保存XML的代码。

使用

1.基本使用

1.1 编写User类

package org.black.demo.xstream;

import java.io.Serializable;
import java.util.Arrays;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * 用户
 */
@XmlRootElement
//@XmlElement
public class User implements Serializable
{
    // serialVersionUID IDE自动生成的序列化ID
	private static final long serialVersionUID = -3552351542858137630L;
	// 姓名
	private String name;
	// 性别
	private String sex;
	// 年龄
	private Integer age;
	// 身高
	private Double height;
	// 分数
	private Double[] points;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Double getHeight() {
		return height;
	}
	public void setHeight(Double height) {
		this.height = height;
	}
	
	public Double[] getPoints() {
		return points;
	}
	public void setPoints(Double[] points) {
		this.points = points;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", sex=" + sex + ", age=" + age + ", height=" + height + ", points=" + Arrays.toString(points) +"]";
	}
}

1.2 编写测试类

package org.black.demo.jaxb;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.black.demo.xstream.User;

import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

public class JavaArcXMlBean {

	public static void main(String[] args) {

		try {
			// contextPath 是Java对象的包名集合,test.jaxb就是包名
			JAXBContext jc = JAXBContext.newInstance(User.class);
			// marshalling 是计算机科学中把一个对象的内存表示变换为适合存储或发送的数据格式的过程
			// marshaller 是控制 marshalling 处理
			Marshaller marshaller = jc.createMarshaller();
			User admin = new User();
			admin.setName("管理员111");
			admin.setAge(27);
			admin.setHeight(180.00);
			admin.setSex("男");
			Double[] points = new Double[2];
			points[0] = 182.00;
			points[1] = 100.00;

			admin.setPoints(points);
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));
			// 将Java对象序列化为xml 文件
			ByteOutputStream bo = new ByteOutputStream();
			marshaller.marshal(admin, bo);
			bo.flush();
			bo.close();
			ByteInputStream bi =  bo.newInputStream();
			System.out.println("序列化后:" + new  String (bi.getBytes())); 
			Unmarshaller unmarshaller = jc.createUnmarshaller();
			// 真正反序列化 xml 文件,得到
			User adminCpoy = (User) unmarshaller.unmarshal(bi);
			bi.close();
			System.out.println("adminCpoy:" + adminCpoy);

		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

1.3 验证

序列化后:<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
    <age>27</age>
    <height>180.0</height>
    <name>管理员111</name>
    <points>182.0</points>
    <points>100.0</points>
    <sex>男</sex>
</user>

adminCpoy:User [name=管理员111, sex=男, age=27, height=180.0, points=[182.0, 100.0]]

2 改进版

单独写一个JAXBUtil.Java工具类 提供序列化和反序列化方法.

2.1 JAXBUtil 工具类

package org.black.demo.jaxb;

import java.io.IOException;
import java.io.StringReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

/**
 * JAXB 序列化工具类
 * @author black
 * @date 2021-12-10 18:44:038
 */
public class JAXBUtil {
	
	/**
	 * 序列化为xml字符串
	 * @param obj
	 * @return
	 * @throws JAXBException
	 * @throws IOException 
	 */
	
	public static String serialize(Object obj) throws JAXBException, IOException {
		// contextPath 是Java对象的包名集合,test.jaxb就是包名
		JAXBContext jc;
		StringBuilder builder = new StringBuilder();
		try (ByteOutputStream bo = new ByteOutputStream();) {
			jc = JAXBContext.newInstance(obj.getClass());
			// marshalling 是计算机科学中把一个对象的内存表示变换为适合存储或发送的数据格式的过程
			// marshaller 是控制 marshalling 处理
			Marshaller marshaller = jc.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));
			// 将Java对象序列化为xml 字符串
			marshaller.marshal(obj, bo);
			bo.flush();
			return new String(bo.getBytes(),"utf8");
		}
	}
	
	/**
	 * xml字符串反序列化为对象
	 * @param <T> 
	 * @param in
	 * @param t
	 * @throws JAXBException
	 * @throws ParserConfigurationException 
	 * @throws SAXException 
	 */
	public static <T> T deserialize(String xml, T t) throws JAXBException, SAXException, ParserConfigurationException {
		JAXBContext jc = JAXBContext.newInstance(t.getClass());
		Unmarshaller unmarshaller = jc.createUnmarshaller();
		Source source =  trunSource(xml);
		JAXBElement<? extends Object> et = unmarshaller.unmarshal(source,t.getClass());
		 return (T)et.getValue();
	}
	
	
	private static Source trunSource(String xmlStr) throws SAXException, ParserConfigurationException{
		 StringReader reader = new StringReader(xmlStr); 
	     SAXParserFactory sax = SAXParserFactory.newInstance();  
        sax.setNamespaceAware(false);  
        XMLReader xmlReader = sax.newSAXParser().getXMLReader();
        Source source = new SAXSource(xmlReader, new InputSource(reader));  
		 return source;		
	}
}

2.2 编写 XML 对应类

xml 节点结构:

<root>
    +
	+ ---- <header>
	+
	+ ---- <object>
	+ ---- <object>
    ...
</root>
2.2.1 root 节点
package org.black.demo.jaxb;

import java.util.List;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "root")
public class XMLFileRoot {

	// root 标签属性 id
	@XmlAttribute
	private String id;

	// root 标签属性 type
	@XmlAttribute
	private String type;

	// root 标签子标签 header
	@XmlElement(name = "header")
	private XMLHeader header;

	// XmlElementRef 根据 ContentObject 类型来映射xml 标签
	@XmlElementRef
	private List<ContentObject> objects;
	
	// 无参构造器必须存在,否则报"does not have a no-arg default constructor"
	public XMLFileRoot() {
	}
	
	public XMLFileRoot(String id, String type) {
		super();
		this.id = id;
		this.type = type;
	}

	public void setHeader(XMLHeader header) {
		this.header = header;
	}

	public void setObjects(List<ContentObject> objects) {
		this.objects = objects;
	}
}

2.2.2 header 节点
package org.black.demo.jaxb;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement(name = "header")
public class XMLHeader {

	// header 标签属性 name
	@XmlAttribute
	private String name;

	// header 标签属性 desc
	@XmlAttribute
	private String desc;
	
	// header 标签的值,示例: <header>"<![CDATA[ p=abc ]]></header>
	@XmlValue
	private String metadate ="<![CDATA[+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs]]>";

	public void setName(String name) {
		this.name = name;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}
}
2.2.3 object 节点(多个)

object 存在公用属性 id 和 desc,这里我提取了一个父类 ContentObject,并用 @XmlSeeAlso 指定 子类使用ContentObject的属性:

package org.black.demo.jaxb;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlSeeAlso;

// @XmlSeeAlso 指示 JAXB 绑定这个类时,也绑定其他类
@XmlSeeAlso(value = {Book.class, Phone.class})
public class ContentObject {
	@XmlAttribute
	protected String id;
	
	@XmlAttribute
	protected String name;
	
}

两个子类 Book 和Phone:

package org.black.demo.jaxb;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="object")
public class Book extends ContentObject{

	// 价格
	@XmlAttribute
	private Double price;
	
	// 无参构造器必须存在,否则报"does not have a no-arg default constructor"
	public Book() {
		
	}
	
	 public Book(String id, String name) {
		this.id = id;
		this.name = name;
	}

	public void setPrice(Double price) {
		this.price = price;
	}
}

package org.black.demo.jaxb;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "object")
public class Phone extends ContentObject {

	// 生产日期
	@XmlAttribute
	private String createDate;

	// 无参构造器必须存在,否则报"does not have a no-arg default constructor"
	public Phone() {

	}

	public Phone(String id, String name) {
		this.id = id;
		this.name = name;
	}

	public void setCreateDate(String createDate) {
		this.createDate = createDate;
	}
}

2.3 编写测试类并进行测试

package org.black.demo.jaxb;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBException;

public class JaxbUtilTest {

	public static void main(String[] args) {
		// root
		XMLFileRoot root = new XMLFileRoot("1", "root");

		// header
		XMLHeader header = new XMLHeader();
		header.setName("xml head");
		header.setDesc("这是Jaxb 生成的xml格式数据");

		root.setHeader(header);

		// object
		List<ContentObject> objects = new ArrayList<ContentObject>();
		Book book = new Book("1", "诛仙");
		// 价格
		book.setPrice(88.00);
		Phone phone = new Phone("2", "苹果手机");
		// 生产日期
		phone.setCreateDate("2022-01-01 00:00:00");
		objects.add(book);
		objects.add(phone);

		root.setObjects(objects);

		// 生成xml
		String xml;
		try {
			xml = JAXBUtil.serialize(root);
			System.out.println("生成的XML :");
			System.out.println(xml);
		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

测试结果:

生成的XML :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root id="1" type="root">
    <header name="xml head" desc="这是Jaxb 生成的xml格式数据">&lt;![CDATA[+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs]]&gt;</header>
    <object price="88.0" id="1" name="诛仙"/>
    <object createDate="2022-01-01 00:00:00" id="2" name="苹果手机"/>
</root>
posted on 2022-09-18 21:38  不安分的黑娃  阅读(91)  评论(0编辑  收藏  举报