- <person age="18">
- <name>pli</name>
- <birthday>2012-50-04</birthday>
- </person>
另外在这里简单说说converter的原理:
其实XStream转换过程就是执行一个个converter的过程,只不过使用的大部分converter都是内建好的,XStream遇到一个待转换的object首先去查找能够转换这个object的转换器(converter),怎么找呢,就是通过converter的canConvert(Class clazz)这个
方法,返回为true就是可以转换。明白了吧。
二、JavaBean和XML互转【非
注解方式
】
准备的JavaBean如下:
Person javabean类
- public class Person {
- private String firstname;
- private String lastname;
- private PhoneNumber phone;
- private PhoneNumber fax;
-
- public Person() {
- super();
- }
-
- public Person(String firstname,String lastname) {
- super();
- this.firstname = firstname;
- this.lastname = lastname;
- }
-
- public String getFirstname() {
- return firstname;
- }
-
- public void setFirstname(String firstname) {
- this.firstname = firstname;
- }
-
- public String getLastname() {
- return lastname;
- }
-
- public void setLastname(String lastname) {
- this.lastname = lastname;
- }
-
- public PhoneNumber getPhone() {
- return phone;
- }
-
- public void setPhone(PhoneNumber phone) {
- this.phone = phone;
- }
-
- public PhoneNumber getFax() {
- return fax;
- }
-
- public void setFax(PhoneNumber fax) {
- this.fax = fax;
- }
-
- @Override
- public String toString() {
- return "Person [firstname=" + firstname + ",lastname=" + lastname
- + ",phone=" + phone + ",fax=" + fax + "]";
- }
-
- }
PhoneNumber javabean类
- public class PhoneNumber {
- private int code;
- private String number;
-
- public PhoneNumber() {
- super();
- }
-
- public PhoneNumber(int code,String number) {
- super();
- this.code = code;
- this.number = number;
- }
-
- public int getCode() {
- return code;
- }
-
- public void setCode(int code) {
- this.code = code;
- }
-
- public String getNumber() {
- return number;
- }
-
- public void setNumber(String number) {
- this.number = number;
- }
-
- @Override
- public String toString() {
- return "PhoneNumber [ code =" + code + ",number=" + number + "]";
- }
转换测试类
1、将JavaBean转换为XML字符串
- public class ConvertTest {
-
- /**
- * 将Person转换成xml字符串
- */
- @Test
- public void personToXML() {
- XStream xstream = new XStream();
- xstream.alias("person",Person.class);
- xstream.alias("phonenumber",PhoneNumber.class);
-
- Person joe = new Person("Joe","Walnes");
- joe.setPhone(new PhoneNumber(123,"1234-456"));
- joe.setFax(new PhoneNumber(123,"9999-999"));
-
- String xml = xstream.toXML(joe);
- System.out.println(xml);
- }
- }
xstream.alias("person",Person.class);
xstream.alias("phonenumber",PhoneNumber.class);
这两句是给对象
加上别名,等价于注解方式里面的@XStreamAlias("person")
标签。
- <person>
- <firstname>Joe</firstname>
- <lastname>Walnes</lastname>
- <phone>
- <code>123</code>
- <number>1234-456</number>
- </phone>
- <fax>
- <code>123</code>
- <number>9999-999</number>
- </fax>
- </person>
2、将xml字符串转换成JavaBean
- @Test
- public void xmlToPerson() {
- String site = "CAN";
- XStream xstream = new XStream();
- xstream.alias("person",PhoneNumber.class);
-
- String xml = "<person><firstname>Joe</firstname><lastname>Walnes</lastname><phone><code>123</code><number>1234-456</number></phone><fax><code>123</code><number>9999-999</number></fax></person>";
- xstream.omitField(Person.class,site);
- Person newJoe = (Person) xstream.fromXML(xml);
- System.out.println(newJoe.toString());
- }
三、XStream的限制:
Xstream已经是很不错的东西了,如果真要找不足,我发现有两点。
1. 反序列化的时候无法使用autodetectAnnotations()
方法通知XStream对象去识别annotation。
还记的前面
代码中xstream.autodetectAnnotations(true); 吗, 这句
代码的意思是告诉XStream对象需要
自动识别annotation, 这在序列化(JAVA bean-->XML)的时候没什么问题。但是在反序列化的时候就有问题了,原因官网上说的比较模糊,总之就是不行,只能通过xstream.processAnnotations(Class clazz) 来显式的
注册需要使用annotation的类才行,如果JAVA bean很多就会比较麻烦。但一般来说JAVA bean在
代码组织结构中都比较集中,如放在听一个package下,这样也好办,可以在程序中将该package下的JAVA bean都
获取,然后使用xstream.processAnnotations(Class[] clazzs) 批量
注册。
2. Null
属性无法被序列化,即
值为空的字段是不会输出到XML的。
之前举的例子JAVA bean中的
属性都是被初始化以后才进行序列化的,如果没有初始化就进行序列化会怎样呢 ,还是举个例子
- @XStreamAlias("person")
- public class Person {
- private String name = "pli";
- @XStreamAsAttribute
- private int age = 19;
- @XStreamImplicit(itemFieldName="girl")
- @XStreamOmitField
- List<String> girlFriends;
- @XStreamConverter(value=DateConverter.class)
- Date birthday = new Date();
-
- public Date getBirthday() {
- return birthday;
- }
-
- public void setBirthday(Date birthday) {
- this.birthday = birthday;
- }
-
- public List<String> getGirlFriends() {
- return girlFriends;
- }
-
- public void setGirlFriends(List<String> girlFriends) {
- this.girlFriends = girlFriends;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getName() {
- return this.name;
- }
- }
我想将其它属性都进行了初始化但是没有将girlFriends这个属性初始化,即使说girlFriends==null. 序列化以后会怎样呢?
- <person age="18">
- <name>pli</name>
- <birthday>2012-36-04</birthday>
- <girlFriends/>
- </person>
有什么办法没,真没啥办法。我查了查源码,确实如果某个
属性为null的话就不进行序列化的,唯一的办法是
修改源码,这个太费事。
另外提一点,XStream也提供了不使用annotation的方式,有兴趣请在XStream的官网上查看。
四、xmlUtils--【xml和javaBean互转工具类】
- package com.openeap.webservice.base;
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.Date;
-
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- import com.openeap.modules.taskBoard.entity.TaskBoardSjToQd;
- import com.thoughtworks.xstream.XStream;
- import com.thoughtworks.xstream.io.xml.DomDriver;
-
- public class XmlUtil {
- private static Logger log = LoggerFactory.getLogger(XmlUtil.class);
-
- /**
- * java 转换成xml
- *
- * @Title: toXml
- * @Description: TODO
- * @param obj
- * 对象实例
- * @return String xml字符串
- */
- public static String toXml(Object obj) {
- XStream xstream = new XStream();
- // XStream xstream=new XStream(new DomDriver()); //直接用jaxp dom来解释
- // XStream xstream=new XStream(new DomDriver("utf-8"));
- // //指定编码解析器,直接用jaxp dom来解释
-
- // //如果没有这句,xml中的根元素会是<包.类名>;或者说:注解根本就没生效,所以的元素名就是类的属性
- xstream.processAnnotations(obj.getClass()); // 通过注解方式的,一定要有这句话
- return xstream.toXML(obj);
- }
-
- /**
- * 将传入xml文本转换成Java对象
- *
- * @Title: toBean
- * @Description: TODO
- * @param xmlStr
- * @param cls
- * xml对应的class类
- * @return T xml对应的class类的实例对象
- *
- * 调用的方法实例:PersonBean person=XmlUtil.toBean(xmlStr,* PersonBean.class);
- */
- public static <T> T toBean(String xmlStr,Class<T> cls) {
- // 注意:不是new Xstream(); 否则报错:java.lang.NoClassDefFoundError:
- // org/xmlpull/v1/XmlPullParserFactory
- XStream xstream = new XStream(new DomDriver());
- xstream.alias(cls.getSimpleName(),cls);
- //xstream.processAnnotations(cls);
- T obj = (T) xstream.fromXML(xmlStr);
- return obj;
- }
-
- /**
- * 写到xml文件中去
- *
- * @Title: writeXMLFile
- * @Description: TODO
- * @param obj
- * 对象
- * @param absPath
- * 绝对路径
- * @param fileName
- * 文件名
- * @return boolean
- */
-
- public static boolean toXMLFile(Object obj,String absPath,String fileName) {
- String strXml = toXml(obj);
- String filePath = absPath + fileName;
- File file = new File(filePath);
- if (!file.exists()) {
- try {
- file.createNewFile();
- } catch (IOException e) {
- log.error("创建{" + filePath + "}文件失败!!!");
- return false;
- }
- }// end if
- OutputStream ous = null;
- try {
- ous = new FileOutputStream(file);
- ous.write(strXml.getBytes());
- ous.flush();
- } catch (Exception e1) {
- log.error("写{" + filePath + "}文件失败!!!");
- return false;
- } finally {
- if (ous != null)
- try {
- ous.close();
- } catch (IOException e) {
- log.error("写{" + filePath + "}文件关闭输出流异常!!!");
- }
- }
- return true;
- }
-
- /**
- * 从xml文件读取报文
- *
- * @Title: toBeanFromFile
- * @Description: TODO
- * @param absPath
- * 绝对路径
- * @param fileName
- * 文件名
- * @param cls
- * @throws Exception
- * @return T
- */
- public static <T> T toBeanFromFile(String filePath,Class<T>[] cls) throws Exception {
- //String filePath = absPath + fileName;
- InputStream ins = null;
- try {
- ins = new FileInputStream(new File(filePath));
- } catch (Exception e) {
- throw new Exception("读{" + filePath + "}文件失败!",e);
- }
-
- String encode = "UTF-8";// useEncode(cls);
- XStream xstream = new XStream(new DomDriver(encode));
- xstream.processAnnotations(cls);
- /*for(Class tempCls : cls){
- xstream.alias(tempCls.getSimpleName(),tempCls);
- }*/
-
- T obj = null;
- try {
- obj = (T) xstream.fromXML(ins);
- } catch (Exception e) {
- // TODO Auto-generated catch block
- throw new Exception("解析{" + filePath + "}文件失败!",e);
- }
- if (ins != null)
- ins.close();
- return obj;
- }
-
- public static void main(String[] args) {
- // TODO Auto-generated method stub
-
-
-
-
- }
- }