XStream介紹

XStream是一個實現(xiàn)javaBean與XML互相轉換的工具沃但,極大地簡化了開發(fā)人員的對XML的處理

1鹏控、添加依賴

<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.11.1</version>
</dependency>

2利诺、UML類圖

<Document TaskGuid="560eec8a-be14-4398-8c9a-73b68651a129" DataGuid="" DataType=" QueryJYYKTByHourList" >
    <Data>
        <KBH Type="TEXT">卡編號</KBH>
        <DEALRQ Type="TEXT">刷卡日期</DEALRQ>
        <DEALSJ Type="TEXT">刷卡時間</DEALSJ>
        <XLBM Type="TEXT">線路編碼</XLBM>
    </Data>
    <Data>
        <KBH Type="TEXT">卡編號</KBH>
        <DEALRQ Type="TEXT">刷卡日期</DEALRQ>
        <DEALSJ Type="TEXT">刷卡時間</DEALSJ>
        <XLBM Type="TEXT">線路編碼</XLBM>
    </Data>
…數(shù)據(jù)重復出現(xiàn)
</Document> 

假設現(xiàn)在需要將上面的xml轉換為一個JavaBean,那么首先需要分析這個XML的結構训挡,根節(jié)點是Document澳骤,有三個屬性TaskGuid、DataGuid舍哄、DataType宴凉,有許多個子節(jié)點Data誊锭,每個Data節(jié)點都有四個子節(jié)點:KBH表悬、DEALRQ、DEALSJ丧靡、XLBM蟆沫。可以采用這種思路:用一個Document類:有四個字段温治,TaskGuid饭庞、DataGuid、DataType與一個Data的集合熬荆。每一個Data都有四個字段:KBH舟山、DEALRQ、DEALSJ卤恳、XLBM累盗,每個字段都有一個Type和一個值。

UML類圖如下:

類的關系.png

Document和Data是聚合關系突琳,Data脫離了Document可以獨立存在若债,Data和Kbh、Dealrq拆融、Dealsj與Xlbm是組合關系蠢琳,這四個脫離了Data就不能獨立存在。

3镜豹、XStream注解

主要使用
@XStreamAlias(“alis”)java對象在xml中以標簽的形式顯示時傲须,如果名字與類名或者屬性名不一致,可以使用該標簽并在括號內(nèi)注明別名趟脂。
@XStreamOmitField在輸出XML的時候忽略該屬性
@XStreamImplicit如果該屬性是一個列表或者數(shù)組躏碳,在XML中不顯示list或者Array字樣
@XStreamAsAttribute該屬性不單獨顯示成XML節(jié)點,而是作為屬性顯示出來
@XStreamConverter設置轉換器
@XStreamConverters converter主要用于將某些字段進行復雜的轉換散怖,轉換過程寫在一個類中菇绵。
然后將其注冊到XStream。

工具類:

public class XsteamUtil {
    public static Object toBean(Class<?> clazz, String xml) {
        Object xmlObject = null;
            XStream xstream = new XStream();
            xstream.processAnnotations(clazz);
            xstream.autodetectAnnotations(true);
            xmlObject= xstream.fromXML(xml);
            return xmlObject;
    }
}

在SpringBoot中可以使用@Bean來進行IOC镇眷,設置xstream.autodetectAnnotations(true);來處理注解

如果要進行xml轉JavaBean的操作咬最,需要設施xstream.alias()

4、具體使用

ReturnResult.java

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.util.List;

@Data
@ToString
@Accessors(chain = true)
@XStreamAlias("Document")
public class ReturnResult {
    @XStreamAlias("TaskGuid")
    @XStreamAsAttribute
    private String taskGuid;
    @XStreamAlias("DataGuid")
    @XStreamAsAttribute
    private String dataGuid;
    @XStreamAlias("DataType")
    @XStreamAsAttribute
    private String dataType;
    @XStreamImplicit
    private List<Record> records;
}

使用了@XStreamAlias注解給類與字段起別名欠动,ReturnResult就對應根節(jié)點Document永乌,Java代碼中變量名提倡使用小寫駝峰命名惑申,所以我對字段也使用的別名。@XStreamAsAttribute不將字段作為節(jié)點來對待而是作為屬性翅雏。 @XStreamImplicit不顯示最外層的集合的根節(jié)點圈驼。

Record.java

import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
@XStreamAlias("Data")
public class Record {
    @XStreamAlias("KBH")
    private CardNo cardNo;
    @XStreamAlias("DEALRQ")
    private DealDate dealDate;
    @XStreamAlias("DEALSJ")
    private DealTime dealTime;
    @XStreamAlias("XLBM")
    private RouteCode routeCode;
}

由于XML文件的節(jié)點名不夠見名知意,所以我使用@XStreamAlias的方式來解決望几。

CardNo.java

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * @author huwen
 * 卡編號
 */
@Data
@NoArgsConstructor
@Accessors(chain = true)
@XStreamAlias("KBH")
@XStreamConverter(value= ToAttributedValueConverter.class, strings={"value"})
public class CardNo {
    @XStreamAlias("Type")
    private String type;
    private String value;
}

一個<KBH Type="TEXT">卡編號</KBH>節(jié)點既有屬性又有值绩脆,所以使用了@XStreamConverter,用xstream自帶的轉換器進行轉換橄抹。

@Test
public void testReturnResult2(){
    XStream xStream = new XStream();
    //由于使用的注解靴迫,將自動檢測注解開啟
    xStream.autodetectAnnotations(true);
    List<Record> records = new ArrayList<>();
    
    //設置對象的屬性值
    CardNo k1 = new CardNo().setType("TEXT").setValue("36283723");
    CardNo k2 = new CardNo().setType("TEXT").setValue("121211");
    DealTime dealTime1 = new DealTime().setType("TEXT").setValue("12");
    DealTime dealTime2 = new DealTime().setType("TEXT").setValue("1");
    DealDate dealDate1 = new DealDate().setType("TEXT").setValue("20200617");
    DealDate dealDate2 = new DealDate().setType("TEXT").setValue("20200520");
    RouteCode routeCode1 = new RouteCode().setType("TEXT").setValue("212");
    RouteCode routeCode2 = new RouteCode().setType("TEXT").setValue("112");
    records.add(new Record().setCardNo(k1).setDealDate(dealDate1).setDealTime(dealTime1).setRouteCode(routeCode1));
    records.add(new Record().setCardNo(k2).setDealDate(dealDate2).setDealTime(dealTime2).setRouteCode(routeCode2));
    ReturnResult result = new ReturnResult().setDataType("QueryJYYKTByHourList").setTaskGuid("560eec8a-be14-4398-8c9a-73b68651a129")
            .setDataGuid("d78whe28eh").setRecords(records);
    
    //轉換為xml格式的字符串
    String s = xStream.toXML(result);
    String s1 =
            "<Document TaskGuid=\"560eec8a-be14-4398-8c9a-73b68651a129\" DataGuid=\"d78whe28eh\" DataType=\"QueryJYYKTByHourList\">\n" +
                    "  <Data>\n" +
                    "    <KBH Type=\"TEXT\">36283723</KBH>\n" +
                    "    <DEALRQ Type=\"TEXT\">20200617</DEALRQ>\n" +
                    "    <DEALSJ Type=\"TEXT\">12</DEALSJ>\n" +
                    "    <XLBM Type=\"TEXT\">212</XLBM>\n" +
                    "  </Data>\n" +
                    "  <Data>\n" +
                    "    <KBH Type=\"TEXT\">121211</KBH>\n" +
                    "    <DEALRQ Type=\"TEXT\">20200520</DEALRQ>\n" +
                    "    <DEALSJ Type=\"TEXT\">1</DEALSJ>\n" +
                    "    <XLBM Type=\"TEXT\">112</XLBM>\n" +
                    "  </Data>\n" +
                    "</Document>";
    System.out.println(s);
    System.out.println(xStream.fromXML(s1));
}

上面的例子將JavaBean轉換為xml。

@Test
    public void testReturnData(){
        XStream xStream = new XStream();
        xStream.autodetectAnnotations(true);
        //必須要加這行代碼楼誓,否則會報錯玉锌,找不到這個類
        xStream.alias("Document",ReturnResult.class);
        String s = "<Document TaskGuid=\"560eec8a-be14-4398-8c9a-73b68651a129\" DataGuid=\"dhshdisds89e\" DataType=\"QueryJYYKTByHourList\">\n" +
                "  <Data>\n" +
                "    <KBH Type=\"TEXT\">12121</KBH>\n" +
                "    <DEALRQ Type=\"TEXT\">2020212</DEALRQ>\n" +
                "    <DEALSJ Type=\"TEXT\">12</DEALSJ>\n" +
                "    <XLBM Type=\"TEXT\">12</XLBM>\n" +
                "  </Data>\n" +
                "  <Data>\n" +
                "    <KBH Type=\"TEXT\">37612</KBH>\n" +
                "    <DEALRQ Type=\"TEXT\">2020312</DEALRQ>\n" +
                "    <DEALSJ Type=\"TEXT\">15</DEALSJ>\n" +
                "    <XLBM Type=\"TEXT\">23</XLBM>\n" +
                "  </Data>\n" +
                "</Document>";
        System.out.println(xStream.fromXML(s));
    }

上面的例子將xml形式的字符串轉換為JavaBean,需要注意的是必須要加xStream.alias("Document",ReturnResult.class);這行代碼疟羹,否則會報com.thoughtworks.xstream.mapper.CannotResolveClassException: Document這個異常主守。

可以看出使用XStream的一般步驟:

  1. 創(chuàng)建XStream對象:XStream xStream = new XStream();
  2. 開始自動檢測注解:xStream.autodetectAnnotations(true);
  3. 進行轉換:fromXML或者toXML

既讓這個XStrem對象經(jīng)常使用,那么在Spring項目中可以使用Spring IOC將它交給Spring容器進行管理榄融,在需要的時候進行注入即可参淫。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市剃袍,隨后出現(xiàn)的幾起案子黄刚,更是在濱河造成了極大的恐慌,老刑警劉巖民效,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憔维,死亡現(xiàn)場離奇詭異,居然都是意外死亡畏邢,警方通過查閱死者的電腦和手機业扒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舒萎,“玉大人程储,你說我怎么就攤上這事”矍蓿” “怎么了章鲤?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咆贬。 經(jīng)常有香客問我败徊,道長,這世上最難降的妖魔是什么掏缎? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任皱蹦,我火速辦了婚禮煤杀,結果婚禮上,老公的妹妹穿的比我還像新娘沪哺。我一直安慰自己沈自,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布辜妓。 她就那樣靜靜地躺著枯途,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嫌拣。 梳的紋絲不亂的頭發(fā)上柔袁,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天呆躲,我揣著相機與錄音异逐,去河邊找鬼。 笑死插掂,一個胖子當著我的面吹牛灰瞻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辅甥,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酝润,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了璃弄?” 一聲冷哼從身側響起要销,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎夏块,沒想到半個月后疏咐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡脐供,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年浑塞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片政己。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡酌壕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出歇由,到底是詐尸還是另有隱情卵牍,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布沦泌,位于F島的核電站糊昙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赦肃。R本人自食惡果不足惜溅蛉,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一公浪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧船侧,春花似錦欠气、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至袁梗,卻和暖如春宜鸯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遮怜。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工淋袖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锯梁。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓即碗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親陌凳。 傳聞我的和親對象是個殘疾皇子剥懒,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容