Knight of the round table

          wansong

          XStream Annotations 入門【翻譯】

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

          首先創(chuàng)建示例的環(huán)境,
          下面介紹的是最基礎(chǔ)的轉(zhuǎn)換器,首先創(chuàng)建一個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)建一個實例,并轉(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)建一個別名:

          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)建立好一個可以供我們實驗的基礎(chǔ)例子了,下面我們來看看XStream的轉(zhuǎn)換器能為我們做些什么:
          2,創(chuàng)建一個Person轉(zhuǎn)換器:
          下面我們來創(chuàng)建一個簡單的轉(zhuǎn)換器,它能:
          1,用來轉(zhuǎn)換Person類
          2,將Person實例轉(zhuǎn)換成XML
          3,將xml轉(zhuǎn)換為Person實例
          首先創(chuàng)建一個PersonConverter類,并讓這個類實現(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)換器是會困難一點。

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

          Person person = (Person) value;
          接著,我們就可以開始輸出數(shù)據(jù)了,首先我們創(chuàng)建一個叫做fullname的節(jié)點,并將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方法,但需要記住,你必須在打開一個節(jié)點之后記住關(guān)閉它。一般來說,執(zhí)行轉(zhuǎn)換的操作在setValue方法調(diào)用時發(fā)生。
          下面,我們進入unmarshal方法,我們使用moveDown和moveUp方法在節(jié)點樹層次中移動,所以,這里我們只需要簡單的moveDown,得到值,再moveUp:

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

          最后,我們得到了一個這樣的轉(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;
          }
          }

          接著,我們在我們的main方法中注冊這個轉(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));
          }
          }

          注意到我們怎么注冊我們的轉(zhuǎn)換器了么?只需要下面簡單的一句:

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

          <person>
            <fullname>Guilherme</fullname>
          </person>
          也許你會說:這只改變了我輸出的樹,我需要用它來轉(zhuǎn)換數(shù)據(jù)。
          下面我們來嘗試在person標簽中創(chuàng)建一個叫做fullname的屬性,而不是新創(chuàng)建一個節(jié)點:
          3,一種可選的方式:
          首先,為Person創(chuàng)建一個toString方法,里面包含了所有能用來重新創(chuàng)建一個Person實例的數(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也會變得更易讀(為person創(chuàng)建別名person之后):

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

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

          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)建了一個GregorianCalendar,得到本地化的DataFormat實例,將字符串轉(zhuǎn)換成Date對象,并賦值給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實現(xiàn)不是線程安全的,所以,不要讓你的轉(zhuǎn)換器持有DataFormat的引用
          2,在經(jīng)過了保存和加載的過程后,該轉(zhuǎn)換器可以將其他Calendar實現(xiàn)轉(zhuǎn)換為GregorianCalendar。如果這不是你希望的,只需要修改canConvert方法,并在類型只有為GregorianCalendar的時候再返回true。
          現(xiàn)在,我們得到了下面這個轉(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)建一個main方法:
          1,創(chuàng)建一個calendar,
          2,創(chuàng)建XStream對象
          3,注冊該轉(zhuǎn)換器,并使用Brazilian Portuguese本地化對象
          4,將對象轉(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就是默認的名字。
          下面我們來試試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)建另一個例子:
          我們已經(jīng)創(chuàng)建了兩個對象了,現(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一點問題都沒有。這里,我們實現(xiàn)自己的轉(zhuǎn)換器主要是為了驗證,在這里,我們想重用我們剛才的PersonConverter和CalendarConverter。canConvert仍然很簡單,不過這里,我們不需要再為每一個屬性重新寫轉(zhuǎn)換方法了,我們只需要使用已經(jīng)注冊了的轉(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實例能夠確保不會出現(xiàn)null值,那么我們就可以去掉marshal和unmarshal方法中對null情況的判斷,也不需要循環(huán),而直接根據(jù)tag的名字進行解析:

          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) 評論(0)  編輯  收藏 所屬分類: java

          主站蜘蛛池模板: 河池市| 松阳县| 姚安县| 沈丘县| 章丘市| 定襄县| 万山特区| 高州市| 墨竹工卡县| 正蓝旗| 兰西县| 灌南县| 灵丘县| 大丰市| 湘潭县| 翁源县| 南靖县| 呼和浩特市| 柳林县| 剑川县| 潮安县| 长乐市| 平罗县| 龙川县| 庄河市| 阳东县| 承德县| 稻城县| 密山市| 资源县| 沽源县| 古田县| 北碚区| 望奎县| 新干县| 泗水县| 原阳县| 那曲县| 陇川县| 岳池县| 平塘县|