java 利用Xstream生成和解析xml,知识结构:
1.Xstream简介;
2.Xstream注解常用知识:
@XStreamAlias("message") 别名注解
作用目标: 类,字段
@XStreamImplicit 隐式集合
@XStreamImplicit(itemFieldName="part")
作用目标: 集合字段
@XStreamConverter(SingleValueCalendarConverter.class) 注入转换器
作用目标: 对象
@XStreamAsAttribute 转换成属性
作用目标: 字段
@XStreamOmitField 忽略字段
作用目标: 字段
Auto-detect Annotations 自动侦查注解
xstream.autodetectAnnotations(true);
自动侦查注解与XStream.processAnnotations(Class[] cls)的区别在于性能.自动侦查注解将缓存所有类的类型.
3.案例分析: (1)同一标签下多个同名元素;
(2)同一标签下循环多个对象;
1.Xstream简介;
使用限制: JDK版本不能<1.5.
虽然预处理注解是安全的,但自动侦查注解可能发生竞争条件.
特点:
简化的API;
无映射文件;
高性能,低内存占用;
整洁的XML;
不需要修改对象;支持内部私有字段,不需要setter/getter方法,final字段;非公有类,内部类;类不需要默认构造器,完全对象图支持.维护对象引用计数,循环引用. i
提供序列化接口;
自定义转换类型策略;
详细的错误诊断;
快速输出格式;当前支持 JSON 和 morphing.
使用场景
Transport 转换
Persistence 持久化对象
Configuration 配置
Unit Tests 单元测
隐式集合
当我们使用集合类时不想显示集合,只显示里面的元素即可.
使用隐式集合前:
<list>
<element />
<element />
<list>
使用隐式集合:
xstream.addImplicitCollection(Person.class, "list");
使用隐式集合后:
<element />
<element />
2.Xstream注解常用知识:
@XStreamAlias("message") 别名注解
作用目标: 类,字段
@XStreamImplicit 隐式集合
@XStreamImplicit(itemFieldName="part")
作用目标: 集合字段
@XStreamConverter(SingleValueCalendarConverter.class) 注入转换器
作用目标: 对象
@XStreamAsAttribute 转换成属性
作用目标: 字段
@XStreamOmitField 忽略字段
作用目标: 字段
Auto-detect Annotations 自动侦查注解
xstream.autodetectAnnotations(true);
自动侦查注解与XStream.processAnnotations(Class[] cls)的区别在于性能.自动侦查注解将缓存所有类的类型.
3.案例分析: (1)同一标签下多个同名元素;
(2)同一标签下循环多个对象;
标签:
XStream
代码片段(12) [全屏查看所有代码]
1. [代码]1.实体类:PersonBean
01 | import java.util.List; |
02 |
03 | import com.thoughtworks.xstream.annotations.XStreamAlias; |
04 | import com.thoughtworks.xstream.annotations.XStreamImplicit; |
05 |
06 | /** |
07 | *@ClassName:PersonBean |
08 | *@author: chenyoulong Email: chen.youlong@payeco.com |
09 | *@date :2012-9-28 下午3:10:47 |
10 | *@Description:TODO |
11 | */ |
12 | @XStreamAlias ( "person" ) |
13 | public class PersonBean { |
14 | @XStreamAlias ( "firstName" ) |
15 | private String firstName; |
16 | @XStreamAlias ( "lastName" ) |
17 | private String lastName; |
18 | |
19 | @XStreamAlias ( "telphone" ) |
20 | private PhoneNumber tel; |
21 | @XStreamAlias ( "faxphone" ) |
22 | private PhoneNumber fax; |
23 | |
24 | //测试一个标签下有多个同名标签 |
25 | @XStreamAlias ( "friends" ) |
26 | private Friends friend; |
27 | |
28 | //测试一个标签下循环对象 |
29 | @XStreamAlias ( "pets" ) |
30 | private Pets pet; |
31 | |
32 | |
33 | //省略setter和getter |
34 | } |
2. [代码]2.实体类:PhoneNumber
01 | @XStreamAlias ( "phoneNumber" ) |
02 | public class PhoneNumber{ |
03 | @XStreamAlias ( "code" ) |
04 | private int code; |
05 | @XStreamAlias ( "number" ) |
06 | private String number; |
07 | |
08 | //省略setter和getter |
09 | |
10 | } |
3. [代码]3.实体类:Friends(一个标签下有多个同名标签 )
01 | /** |
02 | * 用Xstream注解的方式实现:一个标签下有多个同名标签 |
03 | *@ClassName:Friends |
04 | *@author: chenyoulong Email: chen.youlong@payeco.com |
05 | *@date :2012-9-28 下午4:32:24 |
06 | *@Description:TODO 5个name 中国,美国,俄罗斯,英国,法国 |
07 | *http://blog.youkuaiyun.com/menhuanxiyou/article/details/5426765 |
08 | */ |
09 | public static class Friends{ |
10 | @XStreamImplicit (itemFieldName= "name" ) //itemFieldName定义重复字段的名称, |
11 | /*<friends> <friends> |
12 | <name>A1</name> <String>A1</String> |
13 | <name>A2</name> 如果没有,则会变成 =====> <String>A1</String> |
14 | <name>A3</name> <String>A1</String> |
15 | </friends> </friends> |
16 | */ |
17 | private List<String> name; |
18 |
19 | public List<String> getName() { |
20 | return name; |
21 | } |
22 |
23 | public void setName(List<String> name) { |
24 | this .name = name; |
25 | } |
26 | } |
4. [代码]4.1实体类:Animal(同一标签下循环对象实体1)
01 | //测试同一标签下循环某一对象 |
02 | public class Animal{ |
03 | @XStreamAlias ( "name" ) |
04 | private String name; |
05 | @XStreamAlias ( "age" ) |
06 | private int age; |
07 | public Animal(String name, int age){ |
08 | this .name=name; |
09 | this .age=age; |
10 | } |
11 | |
12 | //省略setter和getter |
13 | } |
14 | |
5. [代码]4.2实体类:Pets(同一标签下循环对象实体2)
01 | /** |
02 | * 测试同一标签下循环某一对象 |
03 | *@ClassName:Pets |
04 | *@author: chenyoulong Email: chen.youlong@payeco.com |
05 | *@date :2012-9-28 下午6:26:01 |
06 | *@Description:TODO |
07 | */ |
08 | public class Pets{ |
09 | @XStreamImplicit (itemFieldName= "pet" ) |
10 | private List<Animal> animalList; |
11 | |
12 | public List<Animal> getAnimalList() { |
13 | return animalList; |
14 | } |
15 |
16 | public void setAnimalList(List<Animal> animalList) { |
17 | this .animalList = animalList; |
18 | } |
19 | |
20 | } |
6. [代码]5.main函数示例1:toxml
01 | import com.thoughtworks.xstream.XStream; |
02 | import com.thoughtworks.xstream.io.json.JsonWriter.Format; |
03 | import com.thoughtworks.xstream.io.xml.DomDriver; |
04 |
05 | /** |
06 | *@ClassName:PersonTest |
07 | *@author: chenyoulong |
08 | *@date :2012-9-28 下午3:25:09 |
09 | *@Description:TODO |
10 | */ |
11 | public class PersonTest { |
12 |
13 | /** |
14 | * @Title: main |
15 | * @Description: TODO |
16 | * @param args |
17 | * @return void |
18 | */ |
19 | public static void main(String[] args) { |
20 | // TODO Auto-generated method stub |
21 | |
22 | PersonBean per= new PersonBean(); |
23 | per.setFirstName( "chen" ); |
24 | per.setLastName( "youlong" ); |
25 | |
26 | PhoneNumber tel= new PhoneNumber(); |
27 | tel.setCode( 137280 ); |
28 | tel.setNumber( "137280968" ); |
29 | |
30 | PhoneNumber fax= new PhoneNumber(); |
31 | fax.setCode( 20 ); |
32 | fax.setNumber( "020221327" ); |
33 | per.setTel(tel); |
34 | per.setFax(fax); |
35 | |
36 | |
37 | //测试一个标签下有多个同名标签 |
38 | List<String> friendList= new ArrayList<String>(); |
39 | friendList.add( "A1" ); |
40 | friendList.add( "A2" ); |
41 | friendList.add( "A3" ); |
42 | Friends friend1= new Friends(); |
43 | friend1.setName(friendList); |
44 | per.setFriend(friend1); |
45 | |
46 | //测试一个标签下循环对象 |
47 | Animal dog= new Animal( "Dolly" , 2 ); |
48 | Animal cat= new Animal( "Ketty" , 2 ); |
49 | List<Animal> petList= new ArrayList<Animal>(); |
50 | petList.add(dog); |
51 | petList.add(cat); |
52 | Pets pet= new Pets(); |
53 | pet.setAnimalList(petList); |
54 | per.setPet(pet); |
55 | |
56 | //java对象转换成xml |
57 | String xml=XmlUtil.toXml(per); |
58 | System.out.println( "xml===" +xml); |
59 | |
60 | } |
61 | } |
7. [代码]xml效果图
01 | xml===<person> |
02 | <firstName>chen</firstName> |
03 | <lastName>youlong</lastName> |
04 | <telphone> |
05 | <code> 137280 </code> |
06 | <number> 137280968 </number> |
07 | </telphone> |
08 | <faxphone> |
09 | <code> 20 </code> |
10 | <number> 020221327 </number> |
11 | </faxphone> |
12 | <friends> |
13 | <name>A1</name> |
14 | <name>A2</name> |
15 | <name>A3</name> |
16 | </friends> |
17 | <pets> |
18 | <pet> |
19 | <name>doly</name> |
20 | <age> 2 </age> |
21 | </pet> |
22 | <pet> |
23 | <name>Ketty</name> |
24 | <age> 2 </age> |
25 | </pet> |
26 | </pets> |
27 | </person> |
8. [代码]5.2 main函数示例2:toBean
01 | public static void main(String[] args) { |
02 | // TODO Auto-generated method stub |
03 | |
04 | //toXml |
05 | // String xmlStr=new PersonTest().toXml(); |
06 | |
07 | //toBean |
08 | // PersonBean per=new PersonTest().toBean(); |
09 | String xmlStr= "<person>" + |
10 | "<firstName>chen</firstName>" + |
11 | "<lastName>youlong</lastName>" + |
12 | "<telphone>" + |
13 | "<code>137280</code>" + |
14 | "<number>137280968</number>" + |
15 | "</telphone>" + |
16 | "<faxphone>" + |
17 | "<code>20</code>" + |
18 | "<number>020221327</number>" + |
19 | "</faxphone>" + |
20 | "<friends>" + |
21 | "<name>A1</name>" + |
22 | "<name>A2</name>" + |
23 | "<name>A3</name>" + |
24 | "</friends>" + |
25 | "<pets>" + |
26 | "<pet>" + |
27 | "<name>doly</name>" + |
28 | "<age>2</age>" + |
29 | "</pet>" + |
30 | "<pet>" + |
31 | "<name>Ketty</name>" + |
32 | "<age>2</age>" + |
33 | "</pet>" + |
34 | "</pets>" + |
35 | "</person>" ; |
36 | //用泛型的知识 |
37 | PersonBean person=XmlUtil.toBean(xmlStr, PersonBean. class ); |
38 | System.out.println( "person=firstname==" +person.getFirstName()); |
39 | System.out.println( "person==Friends==name1==" +person.getFriend().getName().get( 0 )); |
40 | System.out.println( "person==Pets==name2==" +person.getPet().getAnimalList().get( 1 ).getName()); |
41 |
42 | /* |
43 | //效果与以下方法类同,(以下代码较为直观) |
44 | XStream xstream=new XStream(new DomDriver()); //注意:不是new Xstream(); 否则报错: |
45 |
46 | xstream.processAnnotations(PersonBean.class); |
47 | PersonBean person=(PersonBean)xstream.fromXML(xmlStr); |
48 | System.out.println("person=firstname=="+person.getFirstName()); |
49 | System.out.println("person==Friends==name1=="+person.getFriend().getName().get(0)); |
50 | System.out.println("person==Pets==name=="+person.getPet().getAnimalList().get(1).getName()); |
51 | */ |
52 |
53 | |
54 | } |
9. [代码]6.XmlUtil工具类(toxml()和toBean())
001 | /** |
002 | * 输出xml和解析xml的工具类 |
003 | *@ClassName:XmlUtil |
004 | *@author: chenyoulong Email: chen.youlong@payeco.com |
005 | *@date :2012-9-29 上午9:51:28 |
006 | *@Description:TODO |
007 | */ |
008 | public class XmlUtil{ |
009 | /** |
010 | * java 转换成xml |
011 | * @Title: toXml |
012 | * @Description: TODO |
013 | * @param obj 对象实例 |
014 | * @return String xml字符串 |
015 | */ |
016 | public static String toXml(Object obj){ |
017 | XStream xstream= new XStream(); |
018 | // XStream xstream=new XStream(new DomDriver()); //直接用jaxp dom来解释 |
019 | // XStream xstream=new XStream(new DomDriver("utf-8")); //指定编码解析器,直接用jaxp dom来解释 |
020 | |
021 | 如果没有这句,xml中的根元素会是<包.类名>;或者说:注解根本就没生效,所以的元素名就是类的属性 |
022 | xstream.processAnnotations(obj.getClass()); //通过注解方式的,一定要有这句话 |
023 | return xstream.toXML(obj); |
024 | } |
025 | |
026 | /** |
027 | * 将传入xml文本转换成Java对象 |
028 | * @Title: toBean |
029 | * @Description: TODO |
030 | * @param xmlStr |
031 | * @param cls xml对应的class类 |
032 | * @return T xml对应的class类的实例对象 |
033 | * |
034 | * 调用的方法实例:PersonBean person=XmlUtil.toBean(xmlStr, PersonBean.class); |
035 | */ |
036 | public static <T> T toBean(String xmlStr,Class<T> cls){ |
037 | //注意:不是new Xstream(); 否则报错:java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPullParserFactory |
038 | XStream xstream= new XStream( new DomDriver()); |
039 | xstream.processAnnotations(cls); |
040 | T obj=(T)xstream.fromXML(xmlStr); |
041 | return obj; |
042 | } |
043 |
044 | /** |
045 | * 写到xml文件中去 |
046 | * @Title: writeXMLFile |
047 | * @Description: TODO |
048 | * @param obj 对象 |
049 | * @param absPath 绝对路径 |
050 | * @param fileName 文件名 |
051 | * @return boolean |
052 | */ |
053 | |
054 | public static boolean toXMLFile(Object obj, String absPath, String fileName ){ |
055 | String strXml = toXml(obj); |
056 | String filePath = absPath + fileName; |
057 | File file = new File(filePath); |
058 | if (!file.exists()){ |
059 | try { |
060 | file.createNewFile(); |
061 | } catch (IOException e) { |
062 | log.error( "创建{" + filePath + "}文件失败!!!" + Strings.getStackTrace(e)); |
063 | return false ; |
064 | } |
065 | } // end if |
066 | OutputStream ous = null ; |
067 | try { |
068 | ous = new FileOutputStream(file); |
069 | ous.write(strXml.getBytes()); |
070 | ous.flush(); |
071 | } catch (Exception e1) { |
072 | log.error( "写{" + filePath + "}文件失败!!!" + Strings.getStackTrace(e1)); |
073 | return false ; |
074 | } finally { |
075 | if (ous != null ) |
076 | try { |
077 | ous.close(); |
078 | } catch (IOException e) { |
079 | log.error( "写{" + filePath + "}文件关闭输出流异常!!!" + Strings.getStackTrace(e)); |
080 | } |
081 | } |
082 | return true ; |
083 | } |
084 | |
085 | /** |
086 | * 从xml文件读取报文 |
087 | * @Title: toBeanFromFile |
088 | * @Description: TODO |
089 | * @param absPath 绝对路径 |
090 | * @param fileName 文件名 |
091 | * @param cls |
092 | * @throws Exception |
093 | * @return T |
094 | */ |
095 | public static <T> T toBeanFromFile(String absPath, String fileName,Class<T> cls) throws Exception{ |
096 | String filePath = absPath +fileName; |
097 | InputStream ins = null ; |
098 | try { |
099 | ins = new FileInputStream( new File(filePath )); |
100 | } catch (Exception e) { |
101 | throw new Exception( "读{" + filePath + "}文件失败!" , e); |
102 | } |
103 | |
104 | String encode = useEncode(cls); |
105 | XStream xstream= new XStream( new DomDriver(encode)); |
106 | xstream.processAnnotations(cls); |
107 | T obj = null ; |
108 | try { |
109 | obj = (T)xstream.fromXML(ins); |
110 | } catch (Exception e) { |
111 | // TODO Auto-generated catch block |
112 | throw new Exception( "解析{" + filePath + "}文件失败!" ,e); |
113 | } |
114 | if (ins != null ) |
115 | ins.close(); |
116 | return obj; |
117 | } |
118 | |
119 | } |