Knight of the round table

          wansong

          XStream Annotations 入門【翻譯】

          1、簡單的轉(zhuǎn)換器:

          首先創(chuàng)建示例的環(huán)境,
          下面介紹的是最基礎(chǔ)的轉(zhuǎn)換器,首先創(chuàng)建一個(gè)Person類:

          package com.thoughtworks.xstream.examples;
          public class Person {
          private String name;
          public String getName() {
          return name;
          }
          public void setName(String name) {
          this.name = name;
          }
          }

           接著,我們創(chuàng)建一個(gè)實(shí)例,并轉(zhuǎn)化他:

          package com.thoughtworks.xstream.examples;
          import com.thoughtworks.xstream.XStream;
          import com.thoughtworks.xstream.io.xml.DomDriver;
          public class PersonTest {
          public static void main(String[] args) {
          Person person = new Person();
          person.setName("Guilherme");
          XStream xStream = new XStream(new DomDriver());
          System.out.println(xStream.toXML(person));
          }
          }

           如你所料,得到下面的結(jié)果:

          <com.thoughtworks.xstream.examples.Person>
          <name>Guilherme</name>
          </com.thoughtworks.xstream.examples.Person>

          下面我們?yōu)閜erson類創(chuàng)建一個(gè)別名:

          XStream xStream = new XStream(new DomDriver());
          xStream.alias("person", Person.class);
          System.out.println(xStream.toXML(person));

          現(xiàn)在的結(jié)果就很易讀了:

          <person>
          <name>Guilherme</name>
          </person>

          到此,我們已經(jīng)建立好一個(gè)可以供我們實(shí)驗(yàn)的基礎(chǔ)例子了,下面我們來看看XStream的轉(zhuǎn)換器能為我們做些什么:
          2,創(chuàng)建一個(gè)Person轉(zhuǎn)換器:
          下面我們來創(chuàng)建一個(gè)簡單的轉(zhuǎn)換器,它能:
          1,用來轉(zhuǎn)換Person類
          2,將Person實(shí)例轉(zhuǎn)換成XML
          3,將xml轉(zhuǎn)換為Person實(shí)例
          首先創(chuàng)建一個(gè)PersonConverter類,并讓這個(gè)類實(shí)現(xiàn)Converter接口:

          package com.thoughtworks.xstream.examples;
          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 PersonConverter implements Converter {
          public boolean canConvert(Class clazz) {
          return false;
          }
          public void marshal(Object value, HierarchicalStreamWriter writer,
          MarshallingContext context) {
          }
          public Object unmarshal(HierarchicalStreamReader reader,
          UnmarshallingContext context) {
          return null;
          }
          }

          下面,我們首先告訴轉(zhuǎn)換器,我們只能轉(zhuǎn)換Person類,而不是別的類,包括其子類:

          public boolean canConvert(Class clazz) {
          return clazz.equals(Person.class);
          }

          這一步很簡單,除非你是用來處理泛型的轉(zhuǎn)換器是會(huì)困難一點(diǎn)。

          Marshal方法是用來將對(duì)象轉(zhuǎn)換為XML的,他有三個(gè)參數(shù):
          1,我們準(zhǔn)備轉(zhuǎn)換的對(duì)象
          2,我們準(zhǔn)備輸出對(duì)象的writer
          3,當(dāng)前的marshaling context
          首先我們將object轉(zhuǎn)換成Person

          Person person = (Person) value;
          接著,我們就可以開始輸出數(shù)據(jù)了,首先我們創(chuàng)建一個(gè)叫做fullname的節(jié)點(diǎn),并將person的名字傳給他:

          writer.startNode("fullname");
          writer.setValue(person.getName());
          writer.endNode();

          呵呵~很簡單吧,

          public void marshal(Object value, HierarchicalStreamWriter writer,
          MarshallingContext context) {
          Person person = (Person) value;
          writer.startNode("fullname");
          writer.setValue(person.getName());
          writer.endNode();
          }

          我們可以任意次數(shù)的調(diào)用start/end node方法,但需要記住,你必須在打開一個(gè)節(jié)點(diǎn)之后記住關(guān)閉它。一般來說,執(zhí)行轉(zhuǎn)換的操作在setValue方法調(diào)用時(shí)發(fā)生。
          下面,我們進(jìn)入unmarshal方法,我們使用moveDown和moveUp方法在節(jié)點(diǎn)樹層次中移動(dòng),所以,這里我們只需要簡單的moveDown,得到值,再moveUp:

          Person person = new Person();
          reader.moveDown();
          person.setName(reader.getValue());
          reader.moveUp();

          最后,我們得到了一個(gè)這樣的轉(zhuǎn)換器:

          package com.thoughtworks.xstream.examples;
          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 PersonConverter implements Converter {
          public boolean canConvert(Class clazz) {
          return clazz.equals(Person.class);
          }
          public void marshal(Object value, HierarchicalStreamWriter writer,
          MarshallingContext context) {
          Person person = (Person) value;
          writer.startNode("fullname");
          writer.setValue(person.getName());
          writer.endNode();
          }
          public Object unmarshal(HierarchicalStreamReader reader,
          UnmarshallingContext context) {
          Person person = new Person();
          reader.moveDown();
          person.setName(reader.getValue());
          reader.moveUp();
          return person;
          }
          }

          接著,我們?cè)谖覀兊膍ain方法中注冊(cè)這個(gè)轉(zhuǎn)化器:

          package com.thoughtworks.xstream.examples;
          import com.thoughtworks.xstream.XStream;
          import com.thoughtworks.xstream.io.xml.DomDriver;
          public class PersonTest {
          public static void main(String[] args) {
          Person person = new Person();
          person.setName("Guilherme");
          XStream xStream = new XStream(new DomDriver());
          xStream.registerConverter(new PersonConverter());
          xStream.alias("person", Person.class);
          System.out.println(xStream.toXML(person));
          }
          }

          注意到我們?cè)趺醋?cè)我們的轉(zhuǎn)換器了么?只需要下面簡單的一句:

          xStream.registerConverter(new PersonConverter());
          最終得到的結(jié)果是:

          <person>
            <fullname>Guilherme</fullname>
          </person>
          也許你會(huì)說:這只改變了我輸出的樹,我需要用它來轉(zhuǎn)換數(shù)據(jù)。
          下面我們來嘗試在person標(biāo)簽中創(chuàng)建一個(gè)叫做fullname的屬性,而不是新創(chuàng)建一個(gè)節(jié)點(diǎn):
          3,一種可選的方式:
          首先,為Person創(chuàng)建一個(gè)toString方法,里面包含了所有能用來重新創(chuàng)建一個(gè)Person實(shí)例的數(shù)據(jù):

          package com.thoughtworks.xstream.examples;
          public class Person {
          private String name;
          public String getName() {
          return name;
          }
          public void setName(String name) {
          this.name = name;
          }
          public String toString() {
          return getName();
          }
          }

          現(xiàn)在,我們就能把我們的轉(zhuǎn)化器簡寫為:

           

          package com.thoughtworks.xstream.examples;
          import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
          public class PersonConverter extends AbstractSingleValueConverter {
          public boolean canConvert(Class clazz) {
          return clazz.equals(Person.class);
          }
          public Object fromString(String str) {
          Person person = new Person();
          person.setName(string);
          return person;
          }
          }

          現(xiàn)在,輸出的XML也會(huì)變得更易讀(為person創(chuàng)建別名person之后):

          <person>Guilherme</person>
          名字變成了一個(gè)內(nèi)置的值,而不是一個(gè)單獨(dú)的節(jié)點(diǎn)。
          4,轉(zhuǎn)換Date:
          我們已經(jīng)知道Converter接口是怎樣工作的了,現(xiàn)在我們來創(chuàng)建一個(gè)使用Locale對(duì)象轉(zhuǎn)換時(shí)間的轉(zhuǎn)換器:
          在我們的轉(zhuǎn)換器構(gòu)造方法中,我們將傳入一個(gè)Locale對(duì)象,該Locale對(duì)象會(huì)作為一個(gè)成員屬性被轉(zhuǎn)換器持有:

          package com.thoughtworks.xstream.examples;
          import java.util.Locale;
          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 DateConverter implements Converter {
          private Locale locale;
          public DateConverter(Locale locale) {
          super();
          this.locale = locale;
          }
          public boolean canConvert(Class clazz) {
          return false;
          }
          public void marshal(Object value, HierarchicalStreamWriter writer,
          MarshallingContext context) {
          }
          public Object unmarshal(HierarchicalStreamReader reader,
          UnmarshallingContext context) {
          return null;
          }
          }

          現(xiàn)在,讓我們能轉(zhuǎn)換任何繼承了Calendar對(duì)象的類:

          public boolean canConvert(Class clazz) {
                  return Calendar.class.isAssignableFrom(clazz);
          }
          首先,我們來將Calendar轉(zhuǎn)換成本地化的字符串:首先我們把object轉(zhuǎn)化成Calendar,得到Date對(duì)象,并使用DataFormatter來得到一個(gè)本地化的時(shí)間:

          public void marshal(Object value, HierarchicalStreamWriter writer,
          MarshallingContext context) {
          Calendar calendar = (Calendar) value;
          // grabs the date
          Date date = calendar.getTime();
          // grabs the formatter
          DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
          this.locale);
          // formats and sets the value
          writer.setValue(formatter.format(date));
          }

          另一方面,在unmarshall方法中,我們創(chuàng)建了一個(gè)GregorianCalendar,得到本地化的DataFormat實(shí)例,將字符串轉(zhuǎn)換成Date對(duì)象,并賦值給GregorianCalendar。

          public Object unmarshal(HierarchicalStreamReader reader,
                          UnmarshallingContext context) {
                  // creates the calendar
                  GregorianCalendar calendar = new GregorianCalendar();
                  // grabs the converter
                  DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
                                  this.locale);
                  // parses the string and sets the time
                  try {
                          calendar.setTime(formatter.parse(reader.getValue()));
                  } catch (ParseException e) {
                          throw new ConversionException(e.getMessage(), e);
                  }
                  // returns the new object
                  return calendar;
          }

          注意:
          1,記住一些DataFormat實(shí)現(xiàn)不是線程安全的,所以,不要讓你的轉(zhuǎn)換器持有DataFormat的引用
          2,在經(jīng)過了保存和加載的過程后,該轉(zhuǎn)換器可以將其他Calendar實(shí)現(xiàn)轉(zhuǎn)換為GregorianCalendar。如果這不是你希望的,只需要修改canConvert方法,并在類型只有為GregorianCalendar的時(shí)候再返回true。
          現(xiàn)在,我們得到了下面這個(gè)轉(zhuǎn)換器:

          package com.thoughtworks.xstream.examples;
          import java.text.DateFormat;
          import java.text.ParseException;
          import java.util.Calendar;
          import java.util.Date;
          import java.util.GregorianCalendar;
          import java.util.Locale;
          import com.thoughtworks.xstream.converters.ConversionException;
          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 DateConverter implements Converter {
          private Locale locale;
          public DateConverter(Locale locale) {
          super();
          this.locale = locale;
          }
          public boolean canConvert(Class clazz) {
          return Calendar.class.isAssignableFrom(clazz);
          }
          public void marshal(Object value, HierarchicalStreamWriter writer,
          MarshallingContext context) {
          Calendar calendar = (Calendar) value;
          Date date = calendar.getTime();
          DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
          this.locale);
          writer.setValue(formatter.format(date));
          }
          public Object unmarshal(HierarchicalStreamReader reader,
          UnmarshallingContext context) {
          GregorianCalendar calendar = new GregorianCalendar();
          DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
          this.locale);
          try {
          calendar.setTime(formatter.parse(reader.getValue()));
          } catch (ParseException e) {
          throw new ConversionException(e.getMessage(), e);
          }
          return calendar;
          }
          }

          現(xiàn)在,我們來測試一下,創(chuàng)建一個(gè)main方法:
          1,創(chuàng)建一個(gè)calendar,
          2,創(chuàng)建XStream對(duì)象
          3,注冊(cè)該轉(zhuǎn)換器,并使用Brazilian Portuguese本地化對(duì)象
          4,將對(duì)象轉(zhuǎn)化成XML
          代碼如下:

          package com.thoughtworks.xstream.examples;
          import java.util.Calendar;
          import java.util.GregorianCalendar;
          import java.util.Locale;
          import com.thoughtworks.xstream.XStream;
          import com.thoughtworks.xstream.io.xml.DomDriver;
          public class DateTest {
          public static void main(String[] args) {
          // grabs the current date from the virtual machine
          Calendar calendar = new GregorianCalendar();
          // creates the xstream
          XStream xStream = new XStream(new DomDriver());
          // brazilian portuguese locale
          xStream.registerConverter(new DateConverter(new Locale("pt", "br")));
          // prints the result
          System.out.println(xStream.toXML(calendar));
          }
          }

           可以得到類似如下的結(jié)果:

          <gregorian-calendar>Sexta-feira, 10 de Fevereiro de 2006</gregorian-calendar>
          注意,我們沒有為GregorianCalendar創(chuàng)建任何別名,而gregorian-calendar就是默認(rèn)的名字。
          下面我們來試試unmarshal 方法:

          // loads the calendar from the string
          Calendar loaded = (Calendar) xStream
                          .fromXML("<gregorian-calendar>Sexta-feira, 10 de Fevereiro de 2006</gregorian-calendar>");
          然后打印出該日期:

          // prints using the system defined locale
          System.out.println(DateFormat.getDateInstance(DateFormat.SHORT).format(
                          loaded.getTime()));
          得到的結(jié)果為:

          2/10/06
          5,復(fù)雜的轉(zhuǎn)換器:
          創(chuàng)建另一個(gè)例子:
          我們已經(jīng)創(chuàng)建了兩個(gè)對(duì)象了,現(xiàn)在把它們組合起來:

          package com.thoughtworks.xstream.examples;
          public class Birthday {
          private Person person;
          private Calendar date;
          public Person getPerson() {
          return person;
          }
          public void setPerson(Person person) {
          this.person = person;
          }
          public Calendar getDate() {
          return date;
          }
          public void setDate(Calendar date) {
          this.date = date;
          }
          }

           要轉(zhuǎn)換該類,XStream一點(diǎn)問題都沒有。這里,我們實(shí)現(xiàn)自己的轉(zhuǎn)換器主要是為了驗(yàn)證,在這里,我們想重用我們剛才的PersonConverter和CalendarConverter。canConvert仍然很簡單,不過這里,我們不需要再為每一個(gè)屬性重新寫轉(zhuǎn)換方法了,我們只需要使用已經(jīng)注冊(cè)了的轉(zhuǎn)換器來完成轉(zhuǎn)換:

          package com.thoughtworks.xstream.examples;
          import java.util.Calendar;
          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 BirthdayConverter implements Converter {
          public boolean canConvert(Class clazz) {
          return Birthday.class == clazz;
          }
          public void marshal(Object value, HierarchicalStreamWriter writer,
          MarshallingContext context) {
          Birthday birthday = (Birthday)value;
          if (value.getPerson() != null) {
          writer.startNode("person");
          context.convertAnother(value.getPerson());
          writer.endNode();
          }
          if (value.getDate() != null) {
          writer.startNode("birth");
          context.convertAnother(value.getDate());
          writer.endNode();
          }
          }
          public Object unmarshal(HierarchicalStreamReader reader,
          UnmarshallingContext context) {
          Birthday birthday = new Birthday();
          while (reader.hasMoreChildren()) {
          reader.moveDown();
          if ("person".equals(reader.getNodeName())) {
          Person person = (Person)context.convertAnother(birthday, Person.class);
          birthday.setPerson(person);
          } else if ("birth".equals(reader.getNodeName())) {
          Calendar date = (Calendar)context.convertAnother(birthday, Calendar.class);
          birthday.setDate(date);
          }
          reader.moveUp();
          }
          return birthday;
          }
          }

           如果birthday實(shí)例能夠確保不會(huì)出現(xiàn)null值,那么我們就可以去掉marshal和unmarshal方法中對(duì)null情況的判斷,也不需要循環(huán),而直接根據(jù)tag的名字進(jìn)行解析:

          package com.thoughtworks.xstream.examples;
          import java.util.Calendar;
          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 BirthdayConverter implements Converter {
          public boolean canConvert(Class clazz) {
          return Birthday.class == clazz;
          }
          public void marshal(Object value, HierarchicalStreamWriter writer,
          MarshallingContext context) {
          Birthday birthday = (Birthday)value;
          writer.startNode("person");
          context.convertAnother(value.getPerson());
          writer.endNode();
          writer.startNode("birth");
          context.convertAnother(value.getDate());
          writer.endNode();
          }
          public Object unmarshal(HierarchicalStreamReader reader,
          UnmarshallingContext context) {
          Birthday birthday = new Birthday();
          reader.moveDown();
          Person person = (Person)context.convertAnother(birthday, Person.class);
          birthday.setPerson(person);
          reader.moveUp();
          reader.moveDown();
          Calendar date = (Calendar)context.convertAnother(birthday, Calendar.class);
          birthday.setDate(date);
          reader.moveUp();
          return birthday;
          }
          }

          posted on 2010-09-07 21:24 w@ns0ng 閱讀(518) 評(píng)論(0)  編輯  收藏 所屬分類: java

          主站蜘蛛池模板: 丰顺县| 赤城县| 堆龙德庆县| 漳浦县| 台中市| 沙田区| 浦江县| 大丰市| 兴安盟| 墨脱县| 大方县| 山西省| 万安县| 临高县| 西青区| 舒兰市| 湖南省| 汉川市| 乌拉特前旗| 贡山| 靖州| 元江| 恩施市| 阳信县| 隆化县| 合江县| 新源县| 营口市| 揭西县| 金门县| 丰镇市| 阿图什市| 腾冲县| 台安县| 潜江市| 沁源县| 安化县| 同仁县| 镶黄旗| 治县。| 安仁县|