XStream是一套简洁易用的开源类库,用于将Java对象序列化为XML或者将XML反序列化为Java对象,是Java对象和XML之间一个双向转换器。
1.XStream概述
2.快速入门
User.java:
public class User implements Serializable { private static final long serialVersionUID = 1L; private int userId; private String name; public User() {} public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class XStreamSample_01 { private static XStream xstream; static { //创建一个XStream实例并指定一个XML解析器 xstream = new XStream(new DomDriver()); } //初始化转换对象 public static User getUser() { User user = new User(); user.setUserId(1); user.setName("XStreamSample"); return user; } //Java对象转化为XML public static void objectToXML() throws Exception { //1.获得要转化的Java对象实例 User user = XStreamSample_01.getUser(); //2.实例化一个文件输出流 FileOutputStream outputStream = new FileOutputStream("D:\\temporary\\XStream\\user.xml"); //3.将User对象转换为XML,并保存到指定文件 xstream.toXML(user, outputStream); } //XML转化为Java对象 public static void XMLToObject() throws Exception { //实例化一个文件输入流 FileInputStream inputStream = new FileInputStream("D:\\temporary\\XStream\\user.xml"); //将XML文件输入流 User user = (User)xstream.fromXML(inputStream); System.out.println("user's id: " + user.getUserId()); System.out.println("user's name: " + user.getName()); } }
3.使用XStream别名:
XStream别名配置包含三种情况:
①.类别名,用alias(String name, Class type)
②.类成员别名,用aliasField(String alias, Class definedIn, String fieldName)
③.类成员作为属性别名,用aliasAttribute(String alias, String attributeName, String alias)单独命名没有意义,还要通过useAttributeFor(Class definedIn, String fieldName)应用到某个类上。
在XStreamSample_01中添加如下代码:
static { //设置类别名,默认为当前类名加上包名 xstream.alias("user", User.class); //设置类成员名 xstream.aliasField("id", User.class, "userId"); xstream.aliasField("userName", User.class, "name"); }
XStream转换器:转换一些自定义类型
DateConverter.java
public class DateConverter implements Converter { private Locale locale; public DateConverter() { this.locale = Locale.SIMPLIFIED_CHINESE; } public DateConverter(Locale locale) { super(); this.locale = locale; System.out.println("--有参数的构造方法--"); } //判断要转换的类型 @Override public boolean canConvert(Class arg0) { return Date.class.isAssignableFrom(arg0); } //Java对象到XML转换逻辑 @Override public void marshal(Object arg0, HierarchicalStreamWriter arg1, MarshallingContext arg2) { //getDateInstance(..):获取给定语言环境的给定格式化风格的日期格式器 DateFormat formatter = DateFormat.getDateInstance(DateFormat.DATE_FIELD, this.locale); arg1.setValue(formatter.format(arg0)); } //XML到Java对象转换 @Override public Object unmarshal(HierarchicalStreamReader arg0, UnmarshallingContext arg1) { GregorianCalendar calendar = new GregorianCalendar(); DateFormat formatter = DateFormat.getDateInstance(DateFormat.DATE_FIELD, this.locale); try { calendar.setTime(formatter.parse(arg0.getValue())); } catch (ParseException e) { System.out.println(e.getMessage()); } return calendar.getGregorianChange();//获得格里高利历的更改日期 } }
调用:
static { //创建一个XStream实例并指定一个XML解析器 xstream = new XStream(new DomDriver()); xstream.processAnnotations(LoginLog.class); //注册自定义的日期转换器 xstream.registerConverter(new DateConverter(Locale.SIMPLIFIED_CHINESE)); }
问题:书上没有无参构造方法,但是我不定义无参构造方法会报错。并且如果我不在无参构造方法中初始化locale,在DateFormat formatter = DateFormat.getDateInstance(DateFormat.DATE_FIELD, this.locale);这名会报locale空指针。不知道什么原因。
XStream注解:
示例:
//别名注解,作用于类和字段 @XStreamAlias("loginLog") public class LoginLog implements Serializable { //忽略字段,作用于字段 @XStreamOmitField private static final long serialVersionUID = 1L; //转换为属性,作用于字段 @XStreamAsAttribute @XStreamAlias("id") private int loginLogId; @XStreamAlias("userId") private int userId; @XStreamAlias("lastIp") private String ip; @XStreamConverter(DateConverter.class) private Date loginDate; public LoginLog() {} public int getLoginLogId() { return loginLogId; } public void setLoginLogId(int loginLogId) { this.loginLogId = loginLogId; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Date getLoginDate() { return loginDate; } public void setLoginDate(Date loginDate) { this.loginDate = loginDate; } @Override public String toString() { return "用户 " + userId + " 最后一次登陆时间为:" + loginDate; } }
启用XStream提供的注解功能,需要在执行Java对象与XML转换之前,先注册标注了XStream注解的Java对象。
xstream.processAnnotations(LoginLog.class); //自动加载注解Bean //xstream.autodetectAnnotations(true);
流化对象:
public class ObjectStreamSample { private static XStream xstream = new XStream(); //Java对象转化为XML public static LoginLog getLoginLog() { LoginLog loginLog = new LoginLog(); loginLog.setLoginLogId(1); loginLog.setUserId(1); loginLog.setIp("192.168.1.1"); loginLog.setLoginDate(new Date()); return loginLog; } public void objectToXML() throws Exception { LoginLog loginLog = ObjectStreamSample.getLoginLog(); //创建一个PrintWriter,用于输出 PrintWriter writer = new PrintWriter("D:\\temporary\\XStream\\loginLog_02.xml"); //选用一个HierarchicalStreamWriter的实现类来创建输出 PrettyPrintWriter ppw = new PrettyPrintWriter(writer); //CompactWriter cw = new CompactWriter(writer); //创建对象输出流 ObjectOutputStream out = xstream.createObjectOutputStream(ppw); out.writeObject(loginLog); out.close(); } //XML转化为Java对象 public LoginLog xmlToObject() throws Exception { //通过对象流进行输入操作 FileReader reader = new FileReader("D:\\temporary\\XStream\\loginLog_02.xml"); BufferedReader bufferedReader = new BufferedReader(reader); //创建对象输入流 ObjectInputStream input = xstream.createObjectInputStream(bufferedReader); //从XML文件中读取对象 LoginLog loginLog = (LoginLog)input.readObject(); return loginLog; } }
PrettyPrintWriter和CompactWriter的区别在于,用CompactWriter方法输出的为连续的没有分隔的XML文件,而用PrettyPrintWriter方法输出的为有分隔有一定格式的XML文件。