JAXB最佳实践
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAXB最佳实践相关的知识,希望对你有一定的参考价值。
JAXB主要用来实现对象和XML之间的序列化和反序列化。
本文主要总结JAXB基本使用方法和注意事项!
通过下文的XML示例内容进行JAXB的简单实践
<?xml version="1.0" encoding="UTF-8"?> <Provinces> <Province id="B001"> <name>北京</name> <code>30000</code> </Province> <Province id="Z001"> <name>浙江</name> <code>60000</code> </Province> <Province id="J001"> <name>江苏</name> <code>90000</code> <city citycode="90001">南京市</city> <city citycode="90002">盐城市</city> <city citycode="90003">扬州市</city> <city citycode="90004">南通市</city> </Province> </Provinces>
JavaBean to XML
一、分析citys.xml,可以定义三个示例类ProvincesBean,ProvinceBean,CityBean.java
package my.jaxb.bean; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; /** <Provinces> <Province id="B001">... <Province id="B002">... <Province id="J001">... </Provinces> **/ @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "Provinces") public class ProvincesBean { @XmlElement(name = "Province") private List<ProvinceBean> provinces = null; public List<ProvinceBean> getProvinces() { return provinces; } public void setProvinces(List<ProvinceBean> provinces) { this.provinces = provinces; } public String toString() { return "ProvincesBean ( provinces = " + this.provinces + " )"; } }
package my.jaxb.bean; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; /** <Province id="J001"> <name>江苏</name> <code>90000</code> <city citycode="90001">南京市</city> <city citycode="90002">盐城市</city> <city citycode="90003">扬州市</city> <city citycode="90004">南通市</city> </Province> **/ @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "Province") public class ProvinceBean { @XmlAttribute private String id = ""; private String name = ""; private String code = ""; @XmlElement(name = "city") private List<CityBean> citys = null; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<CityBean> getCitys() { return citys; } public void setCitys(List<CityBean> citys) { this.citys = citys; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String toString() { return "ProvinceBean ( id = " + this.id + " name = " + this.name + " code = " + this.code + " citys = " + this.citys + " )"; } }
package my.jaxb.bean; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlValue; /** <city citycode="90001">南京市</city> **/ @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "city") public class CityBean { public CityBean() { } public CityBean(String cityCode, String value) { super(); this.cityCode = cityCode; this.value = value; } @XmlAttribute(name = "citycode") private String cityCode = ""; @XmlValue private String value = ""; public String getCityCode() { return cityCode; } public void setCityCode(String cityCode) { this.cityCode = cityCode; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String toString() { return "CityBean ( cityCode = " + this.cityCode + " value = " + this.value + " )"; } }
二、编写序列化和反序列化的工具类-XmlUtils
package my.jaxb.comm; import java.io.File; import java.io.StringReader; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; public class XmlUtils { // JavaBean to XML public static String toXML(Object obj) { try { JAXBContext context = JAXBContext.newInstance(obj.getClass()); Marshaller marshaller = context.createMarshaller(); // 设置编码格式 marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); // 是否格式化生成的XML marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 是否省略XML头声明信息 marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false); StringWriter writer = new StringWriter(); marshaller.marshal(obj, writer); return writer.toString(); } catch (JAXBException e) { throw new RuntimeException(e.getMessage()); } } // XML to JavaBean public static <MY> MY fromXML(String xml, Class<MY> declareType) { try { JAXBContext context = JAXBContext.newInstance(declareType); Unmarshaller unmarshaller = context.createUnmarshaller(); Object obj = unmarshaller.unmarshal(new StringReader(xml)); return (MY) obj; } catch (JAXBException e) { throw new RuntimeException(e.getMessage()); } } // XML(path) to JavaBean public static <MY> MY fromXMLPath(String xmlPath, Class<MY> declareType) { try { JAXBContext context = JAXBContext.newInstance(declareType); Unmarshaller unmarshaller = context.createUnmarshaller(); Object obj = unmarshaller.unmarshal(new File(xmlPath)); return (MY) obj; } catch (JAXBException e) { throw new RuntimeException(e.getMessage()); } } }
三、编写测试代码,内部实现了JavaBean to XML和XML to JavaBean两个操作
package my.jaxb.test; import java.util.ArrayList; import java.util.List; import my.jaxb.bean.CityBean; import my.jaxb.bean.ProvinceBean; import my.jaxb.bean.ProvincesBean; import my.jaxb.comm.XmlUtils; public class ToXMLFoo { public static void main(String[] args) { ProvincesBean provinces = new ProvincesBean(); provinces.setProvinces(getProvinces()); // JavaBean to XML String xml = XmlUtils.toXML(provinces); System.out.println(xml); System.out.println("------------------------------"); // XML to JavaBean provinces = XmlUtils.fromXML(xml, ProvincesBean.class); System.out.println(provinces); } private static List<ProvinceBean> getProvinces() { List<ProvinceBean> provList = new ArrayList<ProvinceBean>(); ProvinceBean prov = new ProvinceBean(); prov.setId("B001"); prov.setName("北京"); prov.setCode("30000"); ProvinceBean prov2 = new ProvinceBean(); prov2.setId("Z001"); prov2.setName("浙江"); prov2.setCode("60000"); ProvinceBean prov3 = new ProvinceBean(); prov3.setId("J001"); prov3.setName("江苏"); prov3.setCode("90000"); // 单独增加城市 prov3.setCitys(getCitys()); provList.add(prov); provList.add(prov2); provList.add(prov3); return provList; } private static List<CityBean> getCitys() { List<CityBean> cityList = new ArrayList<CityBean>(); CityBean city = new CityBean("90001", "南京市"); CityBean city2 = new CityBean("90002", "盐城市"); CityBean city3 = new CityBean("90003", "扬州市"); CityBean city4 = new CityBean("90004", "南通市"); cityList.add(city); cityList.add(city2); cityList.add(city3); cityList.add(city4); return cityList; } }
四、测试输出结果
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Provinces> <Province id="B001"> <name>北京</name> <code>30000</code> </Province> <Province id="Z001"> <name>浙江</name> <code>60000</code> </Province> <Province id="J001"> <name>江苏</name> <code>90000</code> <city citycode="90001">南京市</city> <city citycode="90002">盐城市</city> <city citycode="90003">扬州市</city> <city citycode="90004">南通市</city> </Province> </Provinces> ------------------------------ ProvincesBean ( provinces = [ProvinceBean ( id = B001 name = 北京 code = 30000 citys = null ), ProvinceBean ( id = Z001 name = 浙江 code = 60000 citys = null ), ProvinceBean ( id = J001 name = 江苏 code = 90000 citys = [CityBean ( cityCode = 90001 value = 南京市 ), CityBean ( cityCode = 90002 value = 盐城市 ), CityBean ( cityCode = 90003 value = 扬州市 ), CityBean ( cityCode = 90004 value = 南通市 )] )] )
XML to JavaBean
一、直接编写测试代码,内部实现了XML to JavaBean的操作
package my.jaxb.test; import my.jaxb.bean.ProvincesBean; import my.jaxb.comm.XmlUtils; public class FromXMLFoo { public static void main(String[] args) { String xmlPath = FromXMLFoo.class.getResource("/").getPath() + "citys.xml"; // XML(path) to JavaBean ProvincesBean bean = XmlUtils.fromXMLPath(xmlPath, ProvincesBean.class); System.out.println(bean); } }
二、测试输出结果
ProvincesBean ( provinces = [ProvinceBean ( id = B001 name = 北京 code = 30000 citys = null ), ProvinceBean ( id = Z001 name = 浙江 code = 60000 citys = null ), ProvinceBean ( id = J001 name = 江苏 code = 90000 citys = [CityBean ( cityCode = 90001 value = 南京市 ), CityBean ( cityCode = 90002 value = 盐城市 ), CityBean ( cityCode = 90003 value = 扬州市 ), CityBean ( cityCode = 90004 value = 南通市 )] )] )
注意事项
1、要序列化的类加上@XmlRootElement注解,否则会报错!
2、JAXB序列化XML时 默认序列化getter和setter,且getter和setter必须成对出现才会被序列化。
3、属性名称,默认序列化出来的类和属性名称默认是首字母转换为小写,若需要控制属性名称需要在getter或setter上
使用 @XmlElement(name = "Province") 指定名称,此处要注意的是@XmlElement也可以放置在getter或setter上都行,
但只能放一个,也就是说不能同时在getter和setter或field字段三者中间任意二者上同时使用 @XmlElement注解!
4、如控制根节点名称?
Re: 使用@XmlRootElement指定name属性即可,如@XmlRootElement(name = "Provinces")。
5、怎么添加命名空间
Re: 使用@XmlRootElement(namespace="my.jaxb") 指定namespace属性,此处不做代码示例。
6、怎么精确控制每个属性名称
Re: JAXB自动转化为首字母小写会导致不可预料的属性名称出现,不嫌麻烦的话为每个属性设置@XmlElement(name=""),想省事的话使用Field字段名称即可。
7、怎么样实现序列化时使用Field字段而不是使用setter和getter
Re: 在要使用的类上面加上@XmlAccessorType(XmlAccessType.FIELD)注解,并指定为XmlAccessType.FIELD,
这里强烈推荐使用@XmlAccessorType(XmlAccessType.FIELD)注解,因为这样你可以精确的控制每个元素的名称,
而不需要为每个属性去设置@XmlElement(name="")注解,当然也可以在Field上使用@XmlElement注解。
8、一个元素既有属性也有文本内容情况如何配置?
Re: 如:<city citycode="90001">南京市</city> ,此时citycode字段通过@XmlAttribute(name = "citycode")控制,value字段通过@XmlValue控制即可。
以上是关于JAXB最佳实践的主要内容,如果未能解决你的问题,请参考以下文章