Springboot中使用Xstream進行XML與Bean 相互轉(zhuǎn)換

在現(xiàn)今的項目開發(fā)中,雖然數(shù)據(jù)的傳輸大部分都是用json格式來進行傳輸,但是xml畢竟也會有一些老的項目在進行使用,正常的老式方法是通過獲取節(jié)點來進行一系列操作,個人感覺太過于復雜、繁瑣。推薦一套簡單的api--XStream類。在理解了原理的情況下看下注解的語法即會使用
例子是把xml映射成bean對象

這個是要映射的xml代碼

<?xml version="1.0" encoding="UTF-8"?>
<c c1="0">
    <d d1="101280101" d2="廣州" d3="guangzhou" d4="廣東"/>
    <d d1="101280102" d2="番禺" d3="panyu" d4="廣東"/>
    <d d1="101280103" d2="從化" d3="conghua" d4="廣東"/>
</c>

xml的代碼結(jié)構(gòu)很簡單,可以看作是城市列表集合
城市的bean

@Data
@AllArgsConstructor
@NoArgsConstructor
public class City {
    private String cityId;
    private String cityName;
    private String cityCode;
    private String province;

這樣就與xml的d元素中的屬性一一對應了
然后再寫個城市列表的bean

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CityList {
    private List<City> cityList;
}

以上的實體類beanset/get方法都使用lombok生成了

下面我們把xml代碼轉(zhuǎn)換成對象

第一種方法是使用 JAXB(Java Architecture for XML Binding) 實現(xiàn)XML與Bean的相互轉(zhuǎn)換

簡介

JAXB是一個業(yè)界的標準,是一項可以根據(jù)XML Schema產(chǎn)生Java類的技術(shù)。該過程中,JAXB也提供了將XML實例文檔反向生成Java對象樹的方法,并能將Java對象樹的內(nèi)容重新寫到 XML實例文檔。
Jaxb 2.0是JDK 1.6的組成部分。我們不需要下載第三方jar包 即可做到輕松轉(zhuǎn)換。Jaxb2使用了JDK的新特性,如:AnnotationGenericType等,需要在即將轉(zhuǎn)換的JavaBean中添加annotation注解。

重要的使用有:

JAXBContext類,是應用的入口,用于管理XML/Java綁定信息。
Marshaller接口,將Java對象序列化為XML數(shù)據(jù)。
Unmarshaller接口,將XML數(shù)據(jù)反序列化為Java對象。
@XmlType,將Java類或枚舉類型映射到XML模式類型
@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或?qū)傩缘男蛄谢?code>FIELD表示JAXB將自動綁定Java類中的每個非靜態(tài)的(static)、非瞬態(tài)的(由@XmlTransient標 注)字段到XML。其他值還有XmlAccessType.PROPERTYXmlAccessType.NONE。
@XmlAccessorOrder,控制JAXB 綁定類中屬性和字段的排序。
@XmlJavaTypeAdapter,使用定制的適配器(即擴展抽象類XmlAdapter并覆蓋marshal()和unmarshal()方法),以序列化Java類為XML。
@XmlElementWrapper ,對于數(shù)組或集合(即包含多個元素的成員變量),生成一個包裝該數(shù)組或集合的XML元素(稱為包裝器)。
@XmlRootElement,將Java類或枚舉類型映射到XML元素。
@XmlElement,將Java類的一個屬性映射到與屬性同名的一個XML元素。
@XmlAttribute,將Java類的一個屬性映射到與屬性同名的一個XML屬性。

具體使用

首先要在之前準備好的bean上加上相關注解
城市Bean

//根元素
@XmlRootElement(name = "d")
//訪問類型,通過字段
@XmlAccessorType(XmlAccessType.FIELD)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class City {
    @XmlAttribute(name = "d1")
    private String cityId;
    @XmlAttribute(name = "d2")
    private String cityName;
    @XmlAttribute(name = "d3")
    private String cityCode;
    @XmlAttribute(name = "d4")
    private String province;
}

城市集合

@XmlRootElement(name = "c")
@XmlAccessorType
(XmlAccessType.FIELD)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CityList {
    @XmlElement(name = "d")
    private List<City> cityList;
}

需要指定bean中的屬性和xml的屬性一一對應

需要有個工具類XmlBuilder,主要是將XML轉(zhuǎn)為指定的對象
里面只需要一個方法

public class XmlBuilder {
    /**
     * 將XML轉(zhuǎn)為指定的POJO
     * @param clazz
     * @param xmlStr
     * @return
     * @throws Exception
     */
    public static Object xmlStrToOject(Class<?> clazz, String xmlStr) throws Exception {
        Object xmlObject = null;
        Reader reader = null;
        JAXBContext context = JAXBContext.newInstance(clazz);
        // XML 轉(zhuǎn)為對象的接口
        Unmarshaller unmarshaller = context.createUnmarshaller();
        reader = new StringReader(xmlStr);
        //以文件流的方式傳入這個string
        xmlObject = unmarshaller.unmarshal(reader);
        if (null != reader) {
            reader.close();
        }
        return xmlObject;
    }
}

這個方法有兩個參數(shù)Class<?> clazz, String xmlStr,Class<?> clazz:指定我們需要轉(zhuǎn)換的對象,xmlStr:需要轉(zhuǎn)的xml字符串

轉(zhuǎn)換方法已經(jīng)寫好了,下面就來調(diào)用,先讀取xml文件,再調(diào)用工具類的方法把XML轉(zhuǎn)為Java對象

public List<City> listCity() throws Exception {
        // 讀取XML文件
        Resource resource = new ClassPathResource("citylist.xml");
        BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream(), "utf-8"));
        StringBuffer buffer = new StringBuffer();
        String line = "";   
        while ((line = br.readLine()) !=null) {
            buffer.append(line);
        }       
        br.close();     
        // XML轉(zhuǎn)為Java對象
        CityList cityList = (CityList)XmlBuilder.xmlStrToOject(CityList.class, buffer.toString());
        return cityList.getCityList();
    }

通過spring提供的ClassPathResource可以讀取,指定類路徑下的資源文件名稱就可以讀取到
下面需要使用 BufferedReaderxml讀取出來,把xml中所有內(nèi)容都以讀取出來并寫入到buffer字符串中.。
后面把需要需要轉(zhuǎn)的對象和讀取出來的內(nèi)容字符串傳入轉(zhuǎn)換方法就可以了

第二種方法是使用XStream

利用XStream在Java對象和XML之間相互轉(zhuǎn)換
簡介
Xstream是一種OXMapping 技術(shù),是用來處理XML文件序列化的框架,在將JavaBean序列化,或?qū)?code>XML文件反序列化的時候,不需要其它輔助類和映射文件,使得XML序列化不再繁索。Xstream也可以將JavaBean序列化成Json或反序列化,使用非常方便。
主要使用
@XStreamAlias(“alis”)java對象在xml中以標簽的形式顯示時,如果名字與類名或者屬性名不一致,可以使用該標簽并在括號內(nèi)注明別名。
@XStreamOmitField在輸出XML的時候忽略該屬性
@XStreamImplicit如果該屬性是一個列表或者數(shù)組,在XML中不顯示list或者Array字樣
@XStreamAsAttribute該屬性不單獨顯示成XML節(jié)點,而是作為屬性顯示出來
@XStreamContainedType
@XStreamConverter設置轉(zhuǎn)換器
@XStreamConverters converter主要用于將某些字段進行復雜的轉(zhuǎn)換,轉(zhuǎn)換過程寫在一個類中。
然后將其注冊到XStream。

springboot使用XStream需要引入依賴

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

然后在bean中加上相關注解
城市bean

@Data
@AllArgsConstructor
@NoArgsConstructor
@XStreamAlias("d")
public class City {
    @XStreamAsAttribute
    @XStreamAlias("d1")
    private String cityId;

    @XStreamAsAttribute
    @XStreamAlias("d2")
    private String cityName;

    @XStreamAlias("d3")
    @XStreamAsAttribute
    private String cityCode;

    @XStreamAsAttribute
    @XStreamAlias("d4")
    private String province;
}

城市集合bean

@Data
@AllArgsConstructor
@NoArgsConstructor
@XStreamAlias("c")
public class CityList {
    @XStreamImplicit(itemFieldName="d")
    private List<City> cityList;
}

重命名注解:@XStreamAlias()
省略集合根節(jié)點:@XStreamImplicit
把字段節(jié)點設置成屬性:@XStreamAsAttribute

這些命名都需要和解析的xml的屬性名一一對應,一旦不對應就會報com.thoughtworks.xstream.mapper.CannotResolveClassException異常,找不到對應的類屬性
集合屬性的需要使用:@XStreamImplicit,不然會報com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$DuplicateFieldException轉(zhuǎn)換器映射異常

同樣也需要寫個轉(zhuǎn)換的工具類

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;
    }
}

傳參也是一樣,Class<?> clazz:指定我們需要轉(zhuǎn)換的對象,xml:需要轉(zhuǎn)的xml字符串
這樣工具類就寫好了

拓展了解

XStream提供了很多方法供我們使用
autodetectAnnotations()自動檢測注解
processAnnotations()應用傳過來的類的注解
fromXML()XML反序列化(JSON也是一樣)
toXML()XML序列化(JSON也是一樣)

自定義解析器
Xstream序列化XML,解析器用StaxDriver
指定解析器:XStream xstream = new XStream(new StaxDriver());
Xstream序列化Json,解析器用JettisonMappedXmlDriver
指定解析器:XStream xstream = new XStream(new JettisonMappedXmlDriver());
也可以不具體指定解析器,也是沒問題的

深入了解

XStreamxstream = new XStream();
默認情況下,XStream會 采用Xpp3庫,XPP3是一種運行效率非常高的XML全解析實現(xiàn)。如果你不想依靠Xpp3庫的話,也可以使用一個標準的JAXP DOM解析器,可以采用以下語句進行初始化:
//不使用XPP3
XStreamxstream = new XStream(new DomDriver());

此xstream實例,為線程安全的,可以供多個線程進行調(diào)用,共享使用。系統(tǒng)提供了多種標識解析器供我們選擇,包括,DomDriver、 JDomDriver、StaxDriver等等。

Xstream提供了對Json的支持,是因為Xstream內(nèi)置了兩個Driver:
1.JsonHierarchicalStreamDriver:不依賴其他類庫,只實現(xiàn) obj->JSON
2.JettisonMappedXmlDriver:依賴jettison類庫,實現(xiàn) JSON->obj or obj->JSON
兩種Driver在處理相同設置的Object時會得到不同的JSON串,JsonHierarchicalStreamDriver得到的串更簡潔,確如官網(wǎng)所說。
JsonHierarchicalStreamDriver有個小問題——默認輸出帶格式的JSON串,結(jié)構(gòu)中帶空格、換行,并且沒有提供修飾方式。

總的來說,Xstream使用起來更簡便,代碼跟簡單,也容易理解,對于xml和Json都提供了支持,不需要其它輔助類和映射文件,使得XML,Json序列化不再繁瑣,我推薦使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,255評論 6 342
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,931評論 1 92
  • 小柳 離開故鄉(xiāng) 轉(zhuǎn)眼十五年 對那座城市 有著復雜的感情 人 是不會喜歡傷心之地的 在那里 有我太多的 痛徹心扉 從...
    小柳姐姐閱讀 250評論 0 0
  • 最近笑笑和冬冬都迷上了妖怪書,有:《稀奇古怪動物園》、《妖怪山》、《妖怪大全》。冬冬最愛的是《稀奇古怪動物園》和《...
    玫瑰腐乳閱讀 523評論 0 0

友情鏈接更多精彩內(nèi)容