??
一、前言
關注微信公眾號回復【原始碼】獲取文章中原始碼,以及封裝的工具類
1、XStream官網
http://x-stream.github.io
2、XStream是什么
XStream是一個簡單的基于Java的類別庫,用來將Java物件序列化成XML(JSON)或反序列化為物件(即:可以輕易的將Java物件和XML檔案相互轉換)
3、XSteam能干什么
XStream在運行時使用Java反射機制對要進行序列化的物件樹的結構進行探索,并不需要對物件作出修改,XStream可以序列化內部欄位,包括私private和final欄位,并且支持非公開類以及內部類,
在預設情況下,XStream不需要配置映射關系,物件和欄位將映射為同名XML元素,但是當物件和欄位名與XML中的元素名不同時,XStream支持指定別名,XStream支持以方法呼叫的方式,或是Java 標注的方式指定別名,
XStream在進行資料型別轉換時,使用系統預設的型別轉換器,同時,也支持用戶自定義的型別轉換器,
4、XStream特點
-
使用方便 - XStream的API提供了一個高層次外觀,以簡化常用的用例
-
無需創建映射 - XStream的API提供了默認的映射大部分物件序列化
-
性能 - XStream快速和低記憶體占用,適合于大物件圖或系統
-
干凈的XML - XStream創建一個干凈和緊湊XML結果,這很容易閱讀
-
不需要修改物件 - XStream可序列化的內部欄位,如private和final欄位,支持非公開類和內部類,默認建構式不是強制性的要求
-
完整物件圖支持 - XStream允許保持在物件模型中遇到的重復參考,并支持回圈參考
-
可自定義的轉換策略 - 定制策略可以允許特定型別的定制被表示為XML的注冊
-
安全框架 - XStream提供了一個公平控制有關解組的型別,以防止操縱輸入安全問題
-
錯誤訊息 - 出現例外是由于格式不正確的XML時,XStream拋出一個統一的例外,提供了詳細的診斷,以解決這個問題
-
另一種輸出格式 - XStream支持其它的輸出格式,如JSON
5、XStream常見的用途
傳輸、持久化、配置、單元測驗
二、XStream入門
1、添加XSteam依賴
/ncom.thoughtworks.xstream /nxstream /n1.4.12 /n/n/n ","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">org.codehaus.jettison /njettison /n1.4.1 /n<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.12</version> </dependency> <dependency> <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> <version>1.4.1</version> </dependency>
2、XStream基本使用
package io.github.xstream.test01;
?
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
public class XStreamTest01 {
public static void main(String[] args) {
Student student = new Student("張三", 20);
XStream xStream = new XStream();//需要XPP3庫
//XStream xStream = new XStream(new DomDriver());//不需要XPP3庫
//XStream xStream = new XStream(new StaxDriver());//不需要XPP3庫開始使用Java 6
//XML序列化
String xml = xStream.toXML(student);
System.out.println(xml);
//XML反序列化
student = (Student) xStream.fromXML(xml);
System.out.println(student);
?
xStream = new XStream(new JettisonMappedXmlDriver());
xStream.setMode(XStream.NO_REFERENCES);
//Json序列化
String json = xStream.toXML(student);
System.out.println(json);
//Json反序列
student = (Student) xStream.fromXML(json);
System.out.println(student);
}
}
?
@AllArgsConstructor
@ToString
class Student {
private String name;
private int age;
}
3、程式運行結果
/n張三 /n20 /n/nSecurity framework of XStream not initialized, XStream is probably vulnerable./nStudent(name=張三, age=20)/n{/"io.github.xstream.test01.Student/":{/"name/":/"張三/",/"age/":20}}/nStudent(name=張三, age=20)/nSecurity framework of XStream not initialized, XStream is probably vulnerable.","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet"><io.github.xstream.test01.Student> <name>張三</name> <age>20</age> </io.github.xstream.test01.Student> Security framework of XStream not initialized, XStream is probably vulnerable. Student(name=張三, age=20) {"io.github.xstream.test01.Student":{"name":"張三","age":20}} Student(name=張三, age=20) Security framework of XStream not initialized, XStream is probably vulnerable.
注意:文中使用到的Lombok注解,Lombok依賴自行添加;XStream序列化XML時需要參考的jar包:xstream-[version].jar、xpp3-[version].jar、xmlpull-[version].jar,當引入xstream依賴后會自動依賴xpp3、xmlpull依賴,XStream序列化JSON需要參考的jar包:jettison-[version].jar,
使用XStream序列化時,對JavaBean沒有任何限制,JavaBean的欄位可以是私有的,也可以沒有getter或setter方法,還可以沒有默認的建構式,
XStream序列化XML時可以允許用戶使用不同的XML決議器,用戶可以使用一個標準的JAXP DOM決議器或自Java 6集成STAX決議器,這樣用戶就不需要依賴xpp3-[version].jar,
三、XStream混疊
1、混疊是一種技術來定制生成XML或者使用XStream特定的格式化XML,假設,一個下面的XML格式是用于序列化/反序列化Student物件,
/n/n /n小米 /n小米手機的描述 /n/n /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">蘋果 /n蘋果手機的描述 /n<student name="張三"> <phone> <brand>小米</brand> <description>小米手機的描述</description> </phone> <phone> <brand>蘋果</brand> <description>蘋果手機的描述</description> </phone> </student>
2、根椐上面的XML格式,我們創建物體類
phones;/n}/n?\n@AllArgsConstructor\n@ToString\nclass Phone {\n private String brand;\n private String description;\n}","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">@AllArgsConstructor
@ToString
class Student {
private String studentName;
private List<Phone> phones;
}
?
@AllArgsConstructor
@ToString
class Phone {
private String brand;
private String description;
}
3、執行代碼
phones = new ArrayList<>();\n phones.add(new Phone(\"小米手機\", \"小米手機的描述\"));\n phones.add(new Phone(\"蘋果手機\", \"蘋果手機的描述\"));\n Student student = new Student(\"張三\", phones);\n?\n XStream xStream = new XStream();//需要XPP3庫\n //XML序列化\n String xml = xStream.toXML(student);\n System.out.println(xml);\n }\n}\n?\n@AllArgsConstructor\n@ToString\nclass Student {\n private String studentName;\n private List phones;\n}\n?\n@AllArgsConstructor\n@ToString\nclass Phone {\n private String brand;\n private String description;\n}","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">package io.github.xstream.test02;
?
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.util.ArrayList;
import java.util.List;
?
public class XStreamTest02 {
public static void main(String[] args) {
List<Phone> phones = new ArrayList<>();
phones.add(new Phone("小米手機", "小米手機的描述"));
phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
Student student = new Student("張三", phones);
?
XStream xStream = new XStream();//需要XPP3庫
//XML序列化
String xml = xStream.toXML(student);
System.out.println(xml);
}
}
?
@AllArgsConstructor
@ToString
class Student {
private String studentName;
private List<Phone> phones;
}
?
@AllArgsConstructor
@ToString
class Phone {
private String brand;
private String description;
}
4、驗證輸出
/n張三 /n/n /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">/n /n小米手機 /n小米手機的描述 /n/n /n蘋果手機 /n蘋果手機的描述 /n<io.github.xstream.test02.Student> <studentName>張三</studentName> <phones> <io.github.xstream.test02.Phone> <brand>小米手機</brand> <description>小米手機的描述</description> </io.github.xstream.test02.Phone> <io.github.xstream.test02.Phone> <brand>蘋果手機</brand> <description>蘋果手機的描述</description> </io.github.xstream.test02.Phone> </phones> </io.github.xstream.test02.Student>
在上面的結果,我們已經看到了Student物件名稱是完全合格的,要替換它作為學生的標簽,按照四、XStream類混疊的步驟
另外,在上述結果中可以看出,所需studentName要重命名來命名,要替換它,按照五、XStream欄位混疊的步驟
在上面的結果,我們可以看到手機標記被添加成為手機串列,替換它,按照六、XStream隱式集合混疊的步驟
在上面的結果,我們可以看到這個名字來作為一個子節點,需要將它作為根節點的屬性,替換它,按照七、XStream屬性混疊的步驟
四、XStream類混疊
1、類混疊是用來創建一個類的XML完全限定名稱的別名,讓我們修改XStreamTest02例子,將下面的代碼添加到XStreamTest02例子里面
xStream.alias("student", Person02.class);
xStream.alias("phone", Phone.class);
2、執行代碼
phones = new ArrayList<>();\n phones.add(new Phone(\"小米手機\", \"小米手機的描述\"));\n phones.add(new Phone(\"蘋果手機\", \"蘋果手機的描述\"));\n Student student = new Student(\"張三\", phones);\n?\n XStream xStream = new XStream();//需要XPP3庫\n xStream.alias(\"student\", Student.class);\n xStream.alias(\"phone\", Phone.class);\n?\n //XML序列化\n String xml = xStream.toXML(student);\n System.out.println(xml);\n }\n}\n?\n@AllArgsConstructor\n@ToString\nclass Student {\n private String studentName;\n private List phones;\n}\n?\n@AllArgsConstructor\n@ToString\nclass Phone {\n private String brand;\n private String description;\n}","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">package io.github.xstream.test02;
?
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.util.ArrayList;
import java.util.List;
?
public class XStreamTest02 {
public static void main(String[] args) {
List<Phone> phones = new ArrayList<>();
phones.add(new Phone("小米手機", "小米手機的描述"));
phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
Student student = new Student("張三", phones);
?
XStream xStream = new XStream();//需要XPP3庫
xStream.alias("student", Student.class);
xStream.alias("phone", Phone.class);
?
//XML序列化
String xml = xStream.toXML(student);
System.out.println(xml);
}
}
?
@AllArgsConstructor
@ToString
class Student {
private String studentName;
private List<Phone> phones;
}
?
@AllArgsConstructor
@ToString
class Phone {
private String brand;
private String description;
}
3、執行結果
/n張三 /n/n /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">/n /n小米手機 /n小米手機的描述 /n/n /n蘋果手機 /n蘋果手機的描述 /n<student> <studentName>張三</studentName> <phones> <phone> <brand>小米手機</brand> <description>小米手機的描述</description> </phone> <phone> <brand>蘋果手機</brand> <description>蘋果手機的描述</description> </phone> </phones> </student>
可以看到<io.github.xstream.test02.Student>和<io.github.xstream.test02.Phone>分別被修改為了<student>和<phone>
五、XStream欄位混疊
1、欄位混疊用于創建以XML欄位的別名,讓我們再次修改原來的XStreamTest02例子,將下面的代碼添加到XStreamTest02例子里面
xStream.aliasField("name", Student.class, "studentName");
2、執行代碼
phones = new ArrayList<>();\n phones.add(new Phone(\"小米手機\", \"小米手機的描述\"));\n phones.add(new Phone(\"蘋果手機\", \"蘋果手機的描述\"));\n Student student = new Student(\"張三\", phones);\n?\n XStream xStream = new XStream();//需要XPP3庫\n xStream.alias(\"student\", Student.class);\n xStream.alias(\"phone\", Phone.class);\n xStream.aliasField(\"name\", Student.class, \"studentName\");\n?\n //XML序列化\n String xml = xStream.toXML(student);\n System.out.println(xml);\n }\n}\n?\n@AllArgsConstructor\n@ToString\nclass Student {\n private String studentName;\n private List phones;\n}\n?\n@AllArgsConstructor\n@ToString\nclass Phone {\n private String brand;\n private String description;\n}","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">package io.github.xstream.test02;
?
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.util.ArrayList;
import java.util.List;
?
public class XStreamTest02 {
public static void main(String[] args) {
List<Phone> phones = new ArrayList<>();
phones.add(new Phone("小米手機", "小米手機的描述"));
phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
Student student = new Student("張三", phones);
?
XStream xStream = new XStream();//需要XPP3庫
xStream.alias("student", Student.class);
xStream.alias("phone", Phone.class);
xStream.aliasField("name", Student.class, "studentName");
?
//XML序列化
String xml = xStream.toXML(student);
System.out.println(xml);
}
}
?
@AllArgsConstructor
@ToString
class Student {
private String studentName;
private List<Phone> phones;
}
?
@AllArgsConstructor
@ToString
class Phone {
private String brand;
private String description;
}
3、執行結果
/n張三 /n/n /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">/n /n小米手機 /n小米手機的描述 /n/n /n蘋果手機 /n蘋果手機的描述 /n<student> <name>張三</name> <phones> <phone> <brand>小米手機</brand> <description>小米手機的描述</description> </phone> <phone> <brand>蘋果手機</brand> <description>蘋果手機的描述</description> </phone> </phones> </student>
可以看到<studentName>被修改為了<name>
六、XStream隱式集合混疊
1、隱式集合混疊時使用的集合是表示在XML無需顯示根,例如,在我們的例子中,我們需要一個接一個,但不是在根節點來顯示每一個節點,讓我們再次修改原來的XStreamTest02例子,將下面的代碼添加到XStreamTest02例子里面
xStream.addImplicitCollection(Student.class, "phones");
2、執行代碼
phones = new ArrayList<>();\n phones.add(new Phone(\"小米手機\", \"小米手機的描述\"));\n phones.add(new Phone(\"蘋果手機\", \"蘋果手機的描述\"));\n Student student = new Student(\"張三\", phones);\n?\n XStream xStream = new XStream();//需要XPP3庫\n xStream.alias(\"student\", Student.class);\n xStream.alias(\"phone\", Phone.class);\n xStream.aliasField(\"name\", Student.class, \"studentName\");\n xStream.addImplicitCollection(Student.class, \"phones\");\n?\n //XML序列化\n String xml = xStream.toXML(student);\n System.out.println(xml);\n }\n}\n?\n@AllArgsConstructor\n@ToString\nclass Student {\n private String studentName;\n private List phones;\n}\n?\n@AllArgsConstructor\n@ToString\nclass Phone {\n private String brand;\n private String description;\n}","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">package io.github.xstream.test02;
?
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.util.ArrayList;
import java.util.List;
?
public class XStreamTest02 {
public static void main(String[] args) {
List<Phone> phones = new ArrayList<>();
phones.add(new Phone("小米手機", "小米手機的描述"));
phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
Student student = new Student("張三", phones);
?
XStream xStream = new XStream();//需要XPP3庫
xStream.alias("student", Student.class);
xStream.alias("phone", Phone.class);
xStream.aliasField("name", Student.class, "studentName");
xStream.addImplicitCollection(Student.class, "phones");
?
//XML序列化
String xml = xStream.toXML(student);
System.out.println(xml);
}
}
?
@AllArgsConstructor
@ToString
class Student {
private String studentName;
private List<Phone> phones;
}
?
@AllArgsConstructor
@ToString
class Phone {
private String brand;
private String description;
}
3、執行結果
/n張三 /n/n /n小米手機 /n小米手機的描述 /n/n /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">蘋果手機 /n蘋果手機的描述 /n<student> <name>張三</name> <phone> <brand>小米手機</brand> <description>小米手機的描述</description> </phone> <phone> <brand>蘋果手機</brand> <description>蘋果手機的描述</description> </phone> </student>
可以看到<phones>被隱藏了
七、XStream屬性混疊
1、屬性混疊用于創建一個成員變數作為XML屬性序列化,讓我們再次修改原來的XStreamTest02例子,將下面的代碼添加到XStreamTest02例子里面
xStream.useAttributeFor(Student.class, "studentName");
2、執行代碼
phones = new ArrayList<>();\n phones.add(new Phone(\"小米手機\", \"小米手機的描述\"));\n phones.add(new Phone(\"蘋果手機\", \"蘋果手機的描述\"));\n Student student = new Student(\"張三\", phones);\n?\n XStream xStream = new XStream();//需要XPP3庫\n xStream.alias(\"student\", Student.class);\n xStream.alias(\"phone\", Phone.class);\n xStream.aliasField(\"name\", Student.class, \"studentName\");\n xStream.addImplicitCollection(Student.class, \"phones\");\n xStream.useAttributeFor(Student.class, \"studentName\");\n?\n //XML序列化\n String xml = xStream.toXML(student);\n System.out.println(xml);\n }\n}\n?\n@AllArgsConstructor\n@ToString\nclass Student {\n private String studentName;\n private List phones;\n}\n?\n@AllArgsConstructor\n@ToString\nclass Phone {\n private String brand;\n private String description;\n}","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">package io.github.xstream.test02;
?
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.util.ArrayList;
import java.util.List;
?
public class XStreamTest02 {
public static void main(String[] args) {
List<Phone> phones = new ArrayList<>();
phones.add(new Phone("小米手機", "小米手機的描述"));
phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
Student student = new Student("張三", phones);
?
XStream xStream = new XStream();//需要XPP3庫
xStream.alias("student", Student.class);
xStream.alias("phone", Phone.class);
xStream.aliasField("name", Student.class, "studentName");
xStream.addImplicitCollection(Student.class, "phones");
xStream.useAttributeFor(Student.class, "studentName");
?
//XML序列化
String xml = xStream.toXML(student);
System.out.println(xml);
}
}
?
@AllArgsConstructor
@ToString
class Student {
private String studentName;
private List<Phone> phones;
}
?
@AllArgsConstructor
@ToString
class Phone {
private String brand;
private String description;
}
3、執行結果
/n/n /n小米手機 /n小米手機的描述 /n/n /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">蘋果手機 /n蘋果手機的描述 /n<student name="張三"> <phone> <brand>小米手機</brand> <description>小米手機的描述</description> </phone> <phone> <brand>蘋果手機</brand> <description>蘋果手機的描述</description> </phone> </student>
可以看到<name>被作為了<student>的屬性
八、XStream包混疊
1、包混疊用于創建一個類XML的完全限定名稱的別名到一個新的限定名稱,讓我們再次修改原來的XStreamTest02例子,將下面代碼
xStream.alias("student", Student.class);
xStream.alias("phone", Phone.class);
修改為
xStream.aliasPackage("xx.xx.xx.xx", "io.github.xstream.test02");
2、執行代碼
phones = new ArrayList<>();\n phones.add(new Phone(\"小米手機\", \"小米手機的描述\"));\n phones.add(new Phone(\"蘋果手機\", \"蘋果手機的描述\"));\n Student student = new Student(\"張三\", phones);\n?\n XStream xStream = new XStream();//需要XPP3庫\n// xStream.alias(\"student\", Student.class);\n// xStream.alias(\"phone\", Phone.class);\n xStream.aliasPackage(\"xx.xx.xx.xx\", \"io.github.xstream.test02\");\n xStream.aliasField(\"name\", Student.class, \"studentName\");\n xStream.addImplicitCollection(Student.class, \"phones\");\n xStream.useAttributeFor(Student.class, \"studentName\");\n?\n //XML序列化\n String xml = xStream.toXML(student);\n System.out.println(xml);\n }\n}\n?\n@AllArgsConstructor\n@ToString\nclass Student {\n private String studentName;\n private List phones;\n}\n?\n@AllArgsConstructor\n@ToString\nclass Phone {\n private String brand;\n private String description;\n}","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">package io.github.xstream.test02;
?
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.util.ArrayList;
import java.util.List;
?
public class XStreamTest02 {
public static void main(String[] args) {
List<Phone> phones = new ArrayList<>();
phones.add(new Phone("小米手機", "小米手機的描述"));
phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
Student student = new Student("張三", phones);
?
XStream xStream = new XStream();//需要XPP3庫
// xStream.alias("student", Student.class);
// xStream.alias("phone", Phone.class);
xStream.aliasPackage("xx.xx.xx.xx", "io.github.xstream.test02");
xStream.aliasField("name", Student.class, "studentName");
xStream.addImplicitCollection(Student.class, "phones");
xStream.useAttributeFor(Student.class, "studentName");
?
//XML序列化
String xml = xStream.toXML(student);
System.out.println(xml);
}
}
?
@AllArgsConstructor
@ToString
class Student {
private String studentName;
private List<Phone> phones;
}
?
@AllArgsConstructor
@ToString
class Phone {
private String brand;
private String description;
}
3、執行結果
/n/n /n小米手機 /n小米手機的描述 /n/n /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">蘋果手機 /n蘋果手機的描述 /n<xx.xx.xx.xx.Student name="張三"> <xx.xx.xx.xx.Phone> <brand>小米手機</brand> <description>小米手機的描述</description> </xx.xx.xx.xx.Phone> <xx.xx.xx.xx.Phone> <brand>蘋果手機</brand> <description>蘋果手機的描述</description> </xx.xx.xx.xx.Phone> </xx.xx.xx.xx.Student>
可以看到包名由io.github.xstream.test02替換為了xx.xx.xx.xx
九、XStream注解
1、前面的四、五、六、七、八步驟都是通過代碼操作的
//xStream.alias("student", Student.class);
//xStream.alias("phone", Phone.class);
xStream.aliasPackage("xx.xx.xx.xx", "io.github.xstream.test02");
xStream.aliasField("name", Student.class, "studentName");
xStream.addImplicitCollection(Student.class, "phones");
xStream.useAttributeFor(Student.class, "studentName");
2、XStream同時也支持注解,使用注解會變得簡單也會達到相同的效果
phones = new ArrayList<>();\n phones.add(new Phone(\"小米手機\", \"小米手機的描述\"));\n phones.add(new Phone(\"蘋果手機\", \"蘋果手機的描述\"));\n Student student = new Student(\"張三\", phones, 20, true);\n \n XStream xStream = new XStream();//需要XPP3庫\n //xStream.processAnnotations(new Class[]{Student.class});\n xStream.autodetectAnnotations(true);\n //XML序列化\n String xml = xStream.toXML(student);\n System.out.println(xml);\n }\n}\n?\n@AllArgsConstructor\n@ToString\n//別名注解\n@XStreamAlias(\"student\")\nclass Student {\n @XStreamAlias(\"name\")\n //把欄位節點設定成屬性\n @XStreamAsAttribute\n private String studentName;\n //省略集合根節點\n @XStreamImplicit\n private List phones;\n //隱藏欄位\n @XStreamOmitField\n private int age;\n //設定轉換器\n @XStreamConverter(value = BooleanConverter.class, booleans = {false}, strings = {\"男\", \"女\"})\n private boolean sex;\n}\n?\n@AllArgsConstructor\n@ToString\n@XStreamAlias(\"phone\")\nclass Phone {\n private String brand;\n private String description;\n}","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet">package io.github.xstream.test03;
?
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.*;
import com.thoughtworks.xstream.converters.basic.BooleanConverter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
?
import java.util.ArrayList;
import java.util.List;
?
public class XStreamTest03 {
public static void main(String[] args) {
List<Phone> phones = new ArrayList<>();
phones.add(new Phone("小米手機", "小米手機的描述"));
phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
Student student = new Student("張三", phones, 20, true);
XStream xStream = new XStream();//需要XPP3庫
//xStream.processAnnotations(new Class[]{Student.class});
xStream.autodetectAnnotations(true);
//XML序列化
String xml = xStream.toXML(student);
System.out.println(xml);
}
}
?
@AllArgsConstructor
@ToString
//別名注解
@XStreamAlias("student")
class Student {
@XStreamAlias("name")
//把欄位節點設定成屬性
@XStreamAsAttribute
private String studentName;
//省略集合根節點
@XStreamImplicit
private List<Phone> phones;
//隱藏欄位
@XStreamOmitField
private int age;
//設定轉換器
@XStreamConverter(value = https://www.cnblogs.com/coding-farmer/p/BooleanConverter.class, booleans = {false}, strings = {"男", "女"})
private boolean sex;
}
?
@AllArgsConstructor
@ToString
@XStreamAlias("phone")
class Phone {
private String brand;
private String description;
}
3、使用注解的話,需要XML序列化之前添加如下代碼
xStream.autodetectAnnotations(true);
或者
xStream.processAnnotations(new Class[]{Student.class});
4、執行結果
/n/n /n小米手機 /n小米手機的描述 /n/n /n蘋果手機 /n蘋果手機的描述 /n男 /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet"><student name="張三"> <phone> <brand>小米手機</brand> <description>小米手機的描述</description> </phone> <phone> <brand>蘋果手機</brand> <description>蘋果手機的描述</description> </phone> <sex>男</sex> </student>
使用注解我們也可以看到也能達到相同的效果
注意:當使用XStream物件處理一個被注解的型別時,XStream物件也會處理所有與其相關的型別的注解資訊,即該型別的父類、父介面、所有子類的注解,
十、XStream自定義轉換器
1、XStream自帶的轉換器
XStream內部有許多轉換器,用于JavaBean物件到XML或JSON之間的轉換,這些轉換器的詳細資訊網址:http://x-stream.github.io/converters.html
2、使用自定義轉換器
package io.github.xstream.test04;
?
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
?
public class XStreamTest04 {
public static void main(String[] args) {
Student student =new Student("張三",19);
XStream xStream = new XStream();
//注冊轉換器
xStream.registerConverter(new StudentConverter());
//序列化
String xml = xStream.toXML(student);
System.out.println(xml);
//反序列化
student=(Student)xStream.fromXML(xml);
System.out.println(student);
}
}
?
@Getter
@Setter
@ToString
@AllArgsConstructor
class Student {
private String name;
private int age;
}
自定義轉換器
package io.github.xstream.test04;
?
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
?
public class StudentConverter implements Converter {
//定義轉換器能轉換的JavaBean型別
@Override
public boolean canConvert(Class type) {
return type.equals(Student.class);
}
?
//把物件序列化成XML或JSON
@Override
public void marshal(Object value, HierarchicalStreamWriter writer,
MarshallingContext context) {
Student student = (Student) value;
writer.startNode("姓名");
writer.setValue(student.getName());
writer.endNode();
writer.startNode("年齡");
writer.setValue(student.getAge() + "");
writer.endNode();
writer.startNode("轉換器");
writer.setValue("自定義的轉換器");
writer.endNode();
}
?
//把XML或JSON反序列化成物件
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
Student student = new Student("", -1);
reader.moveDown();
student.setName(reader.getValue());
reader.moveUp();
reader.moveDown();
student.setAge(Integer.parseInt(reader.getValue()));
reader.moveUp();
return student;
}
}
3、執行結果
/n <姓名>張三姓名>/n <年齡>19年齡>/n <轉換器>自定義的轉換器轉換器>/n/nSecurity framework of XStream not initialized, XStream is probably vulnerable./nStudent(name=張三, age=19)","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet"><student>
<姓名>張三</姓名>
<年齡>19</年齡>
<轉換器>自定義的轉換器</轉換器>
</student>
Security framework of XStream not initialized, XStream is probably vulnerable.
Student(name=張三, age=19)
4、常用的轉換器介面與抽象類
SingleValueConverter:單值轉換介面
AbstractSingleValueConverter:單值轉換抽象類
Converter:常規轉換器介面
十一、XStream物件流
1、物件輸出流
package io.github.xstream.test05;
?
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.io.*;
?
public class XStreamTest05 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
XStreamTest05 xStreamTest04 = new XStreamTest05();
String path = "F:\\test.txt";
XStream xStream = new XStream();//需要XPP3庫
xStream.processAnnotations(Student.class);
xStream.autodetectAnnotations(true);
xStreamTest04.writeObject(xStream, path);
}
?
//物件輸出流方法
public void writeObject(XStream xStream, String path) throws IOException {
Student zs = new Student("張三", 20);
Student ls = new Student("李四", 21);
Student ww = new Student("王五", 22);
ObjectOutputStream objectOutputStream = xStream.createObjectOutputStream(new FileOutputStream(path));
objectOutputStream.writeObject(zs);
objectOutputStream.writeObject(ls);
objectOutputStream.writeObject(ww);
objectOutputStream.writeObject("totalStudent");
objectOutputStream.writeInt(3);
objectOutputStream.close();
}
}
?
@AllArgsConstructor
@ToString
//別名注解
@XStreamAlias("student")
class Student {
@XStreamAlias("name")
//把欄位節點設定成屬性
@XStreamAsAttribute
private String studentName;
private int age;
}
2、在指定路徑中打開test.txt檔案,查看執行結果
/n/n /n20 /n/n /n21 /n/n /n22 /ntotalStudent /n3 /n","classes":[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet"><object-stream> <student name="張三"> <age>20</age> </student> <student name="李四"> <age>21</age> </student> <student name="王五"> <age>22</age> </student> <string>totalStudent</string> <int>3</int> </object-stream>
注意:XStream物件流是通過標準java.io.ObjectOutputStream和java.io.ObjectInputStream物件,因為XML檔案只能有一個根節點,必須包裝在一個序列化的所有元素額外的根節點,這個根節點默認為<object-stream>上面的例子所示,
3、物件輸入流
package io.github.xstream.test05;
?
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.io.*;
?
public class XStreamTest05 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
XStreamTest05 xStreamTest04 = new XStreamTest05();
String path = "F:\\test.txt";
XStream xStream = new XStream();//需要XPP3庫
xStream.processAnnotations(Student.class);
xStream.autodetectAnnotations(true);
xStreamTest04.readObject(xStream, path);
}
?
//物件輸入流方法
public void readObject(XStream xStream, String path) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = xStream.createObjectInputStream(new FileInputStream(path));
System.out.println((Student) objectInputStream.readObject());
System.out.println((Student) objectInputStream.readObject());
System.out.println((Student) objectInputStream.readObject());
System.out.println(objectInputStream.readObject());
System.out.println(objectInputStream.readInt());
}
}
?
@AllArgsConstructor
@ToString
//別名注解
@XStreamAlias("student")
class Student {
@XStreamAlias("name")
//把欄位節點設定成屬性
@XStreamAsAttribute
private String studentName;
private int age;
}
4、執行結果
Student(studentName=張三, age=20)
Student(studentName=李四, age=21)
Student(studentName=王五, age=22)
totalStudent
3
十二、XStream持久化API
1、保存Java物件
?package io.github.xstream.test06;
?
import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
import com.thoughtworks.xstream.persistence.PersistenceStrategy;
import com.thoughtworks.xstream.persistence.XmlArrayList;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.io.File;
import java.util.List;
?
public class XStreamTest06 {
public static void main(String[] args) {
XStreamTest06 xStreamTest06=new XStreamTest06();
xStreamTest06.saveObject();
}
?
//保存Java物件
public void saveObject(){
PersistenceStrategy strategy = new FilePersistenceStrategy(new File("F:\\"));
List list = new XmlArrayList(strategy);
list.add(new Student("張三",13));
list.add(new Student("李四",21));
list.add(new Student("王五",17));
}
}
?
@ToString
@AllArgsConstructor
class Student {
private String name;
private int age;
}
2、運行程式結果,在F磁盤的根路徑可以看到有三個檔案:[email protected]、[email protected]、[email protected],每個物件都被序列化到XML檔案里
3、讀取并洗掉JavaBean物件
package io.github.xstream.test06;
?
import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
import com.thoughtworks.xstream.persistence.PersistenceStrategy;
import com.thoughtworks.xstream.persistence.XmlArrayList;
import lombok.AllArgsConstructor;
import lombok.ToString;
?
import java.io.File;
import java.util.Iterator;
import java.util.List;
?
public class XStreamTest06 {
public static void main(String[] args) {
XStreamTest06 xStreamTest06 = new XStreamTest06();
xStreamTest06.deleteObject();
}
//讀取并洗掉Java物件
public void deleteObject() {
PersistenceStrategy strategy = new FilePersistenceStrategy(new File("F:\\"));
List list = new XmlArrayList(strategy);
for (Iterator it = list.iterator(); it.hasNext(); ) {
System.out.println((Student) it.next());
//洗掉物件序列化檔案
it.remove();
}
}
}
?
@ToString
@AllArgsConstructor
class Student {
private String name;
private int age;
}
4、運行程式結果,可以看到把F磁盤的根路徑[email protected]、[email protected]、[email protected]檔案洗掉了
Security framework of XStream not initialized, XStream is probably vulnerable.
Student(name=張三, age=13)
Student(name=李四, age=21)
Student(name=王五, age=17)
十三、XStream操作JSON
1、XStream序列化JSON的重命名
package io.github.xstream.test07;
?
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import io.github.xstream.test04.StudentConverter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
?
public class XStreamTest07 {
public static void main(String[] args) {
XStreamTest07 xStreamTest07 = new XStreamTest07();
xStreamTest07.serializeJson();
}
?
public void serializeJson() {
Student student = new Student("張三", 19);
XStream xStream = new XStream(new JettisonMappedXmlDriver());//設定Json決議器
xStream.autodetectAnnotations(true);
//JSON序列化
String xml = xStream.toXML(student);
System.out.println(xml);
//JSON反序列化
student = (Student) xStream.fromXML(xml);
System.out.println(student);
}
}
?
@ToString
@AllArgsConstructor
@XStreamAlias("人")
class Student {
@XStreamAlias("姓名")
private String name;
@XStreamAlias("年齡")
private int age;
}
2、運行結果
{"人":{"姓名":"張三","年齡":19}}
Student(name=張三, age=19)
Security framework of XStream not initialized, XStream is probably vulnerable.
注意:XStream序列化JSON的重命名的方式與其序列化成XML的方式一樣!
3、去掉序列化JSON的根節點
?package io.github.xstream.test07;
?
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JsonWriter;
import io.github.xstream.test04.StudentConverter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
?
import java.io.Writer;
?
public class XStreamTest07 {
public static void main(String[] args) {
XStreamTest07 xStreamTest07 = new XStreamTest07();
xStreamTest07.removeRootNode();
}
?
public void removeRootNode() {
Student student = new Student("張三", 19);
XStream xStream = new XStream(new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer writer) {
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
}
});
//Json序列化
String xml = xStream.toXML(student);
System.out.println(xml);
}
}
?
@ToString
@AllArgsConstructor
@XStreamAlias("人")
class Student {
@XStreamAlias("姓名")
private String name;
@XStreamAlias("年齡")
private int age;
}
4、運行結果
{
"name": "張三",
"age": 19
}
注意:去掉根節點后的JSON串是不能反序列化的,因為XStream不知道它的型別,
5、JSON的決議器區別
前面兩個例子使用了不同的JSON決議器,這里說明他們的不同之處:
-
JettisonMappedXmlDriver:是支持序列化和反序列化Json的,
-
JsonHierarchicalStreamDriver:只支持序列化,不支持反序列化,
參考:
http://x-stream.github.io
https://www.yiibai.com/xstream
https://www.cnblogs.com/LiZhiW/p/4313493.html
?
● 別在 Java 代碼里亂打日志了,這才是正確的打日志姿勢!
● 高可用Redis服務架構分析與搭建
● 8 種方案,幫你解決重復提交問題!請拿走
● IDEA 解決 Maven 依賴沖突的高能神器,這一篇夠不夠?
● 你連微服務的網關都說不清楚,還天天鼓搗著要把專案拆分微服務?
?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/227357.html
標籤:Java
上一篇:點擊a標簽中的鏈接不能觸發頁面跳轉(跳轉到data.url),滑鼠的點擊事件也只有ul和li標簽,偶爾出現a標簽
