輕鬆搞定XML和對象之間的互轉,不要錯過

前言

在微信訂閱號和支付寶生活號日常開發中,我們會涉及到對象和XML之間的相互轉換。

輕鬆搞定XML和對象之間的互轉,就它了!

比如我們可以利用StringBuilder去直接拼接來構造XML

    /**
     * 構造基礎的響應消息
     * 
     * @return
     */
    public static String buildBaseAckMsg(String fromUserId) {
        StringBuilder sb = new StringBuilder();
        sb.append("<XML>");
        sb.append("<ToUserId><![CDATA[" + fromUserId + "]]></ToUserId>");
        sb.append("<AppId><![CDATA[" + AlipayServiceEnvConstants.APP_ID + "]]></AppId>");
        sb.append("<CreateTime>" + Calendar.getInstance().getTimeInMillis() + "</CreateTime>");
        sb.append("<MsgType><![CDATA[ack]]></MsgType>");
        sb.append("</XML>");
        return sb.toString();
    }

作爲像我這麼懶得程序員,肯定會去找大佬寫好的輪子,這就是我和XStream相遇的契機。下面我們一起走進XStream

一.關於 XStream

Xstream 是一個簡單的庫,用於將對象序列化爲 XML 然後再序列化回來。

二.簡單入門

2.1 創建要序列化的類

這裏有幾個簡單的類,XStream 可以將這些類的實例轉換爲 XML,然後再轉換回來。

public class Person {
  private String firstname;
  private String lastname;
  private PhoneNumber phone;
  private PhoneNumber fax;
  // ... constructors and methods
}

public class PhoneNumber {
  private int code;
  private String number;
  // ... constructors and methods
}

注意: 注意這些字段是私有的。Xstream 不關心字段的可見性。不需要getters or setters。此外,XStream 並不限制你擁有一個默認構造函數

2.2 初始化 XStream

引入依賴

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

要使用 XStream,只需實例化 XStream 類:

XStream xstream = new XStream();

2.3.將序列化對象轉爲xml

讓我們創建一個 Person 實例並填充它的字段:

        Person person = new Person("Joe", "milo");
        person.setPhone(new PhoneNumber(123,"1234-456"));
        person.setFax(new PhoneNumber(123,"999-456"));

現在,要將其轉換爲XML,只需要簡單的調用XStream的toXML()方法

String xml = xstream.toXML(person);

 

輕鬆搞定XML和對象之間的互轉,就它了!

 

現在,爲了使 XStream 輸出的 XML 更簡潔,可以爲 XML 元素名的自定義類名創建別名。這是使用 XStream 所需的惟一映射類型,當然這是可選的。

xstream.alias("person",Person.class);

我們會發現XML變得更簡潔

輕鬆搞定XML和對象之間的互轉,就它了!

2.4.將XML反序列化對象

首先,我們重寫Person對象的toString()

    @Override
    public String toString() {
        return "Person{" +
                "firstname='" + firstname + ''' +
                ", lastname='" + lastname + ''' +
                ", phone=" + phone +
                ", fax=" + fax +
                '}';
    }

要重構一個對象,我們只需調用fromXML()方法

        XStream xstream = new XStream();
        xstream.alias("person",Person.class);
        //xml字符串
        String xmldemo = "<?xml version="1.0" ?><person><firstname>Joe</firstname><lastname>milo</lastname><phone><code>123</code><number>1234-456</number></phone><fax><code>123</code><number>999-456</number></fax></person>";
        Person o = (Person)xstream.fromXML(xmldemo);
        System.out.println(o.toString());

 

輕鬆搞定XML和對象之間的互轉,就它了!

 

關於更多關於Xstream的操作,大家可以閱讀:

https://www.cnblogs.com/jpfss/p/9836465.html

三.高級入門

在高級入門中,我們以支付寶生活號開發爲例,採用Xstream的註解開發來完成事件訂閱過程中的xml報文相關的操作

3.1 項目搭建

首先我們搭建項目springboot-xstream,當然你可以在

https://gitee.com/milogenius/milogenius-springboot

找到源代碼,案例位於springboot-xstream模塊下面。由於案例代碼太多,強烈建議大家下載源代碼案例自己跑一跑。

輕鬆搞定XML和對象之間的互轉,就它了!

 

3.2 相關類解釋

輕鬆搞定XML和對象之間的互轉,就它了!

 

3.3 和XStream相關的類

1.AlipayXmlMessage
package com.milo.xstream.xml;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.io.Serializable;
import java.util.Map;

/**
 * 支付寶生活號推送過來的xml消息
 * @author milogenius
 * @date 2020/4/4 15:29
 *
 */
@Data
@Slf4j
@XStreamAlias("XML")
public class AlipayXmlMessage implements Serializable {
  private static final long serialVersionUID = -3586245291677274914L;

  /**
   * 使用dom4j解析的存放所有xml屬性和值的map.
   */
  private Map<String, Object> allFieldsMap;

  ///////////////////////
  // 以下都是支付寶生活號推送過來的消息的xml的element所對應的屬性
  ///////////////////////

  /**AppId*/
  //AppId--->xml中的字段
  //appId --->pojo中的字段
  @XStreamAlias("AppId")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String appId;


  /**用戶userid,用戶唯一標識*/
  @XStreamAlias("FromAlipayUserId")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String fromAlipayUserId;


  /**消息創建時間*/
  @XStreamAlias("CreateTime")
  private Long createTime;

  /**消息類型*/
  @XStreamAlias("MsgType")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String msgType;


  /**事件類型*/
  @XStreamAlias("EventType")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String eventType;

  /**用戶從特定場景關注,帶的自定義參數值*/
  @XStreamAlias("ActionParam")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String actionParam;

  /**支付寶用戶信息*/
  @XStreamAlias("UserInfo")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String userInfo;

  /**消息id 用於消息去重*/
  @XStreamAlias("MsgId")
  private String msgId;




  public static AlipayXmlMessage fromXml(String xml) {
    //修改支付寶生活號變態的消息內容格式,方便解析
    xml = xml.replace("<?xml version=\"1.0\" encoding=\"gbk\"?>", "");
    final AlipayXmlMessage xmlMessage = XStreamTransformer.fromXml(AlipayXmlMessage.class, xml);
    xmlMessage.setAllFieldsMap(XmlUtils.xml2Map(xml));
    return xmlMessage;
  }

  public static AlipayXmlMessage fromXml(InputStream is) {
    return XStreamTransformer.fromXml(AlipayXmlMessage.class, is);
  }



}

2.AlipayXmlOutMessage

package com.milo.xstream.outxml;

import com.milo.xstream.builder.AckBuilder;
import com.milo.xstream.xml.XStreamCDataConverter;
import com.milo.xstream.xml.XStreamTransformer;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import lombok.Data;

import java.io.Serializable;

/**
 * 響應XML
 * @author milogenius
 * @date 2020/4/4 11:57
 *
 */
@XStreamAlias("xml")
@Data
public abstract class AlipayXmlOutMessage implements Serializable {
  private static final long serialVersionUID = -381382011286216263L;

  /**接受者userid*/
  @XStreamAlias("ToUserId")
  @XStreamConverter(value = XStreamCDataConverter.class)
  protected String toUserId;

  /**支付寶生活號appid*/
  @XStreamAlias("AppId")
  @XStreamConverter(value = XStreamCDataConverter.class)
  protected String appId;

  /**創建時間*/
  @XStreamAlias("CreateTime")
  protected Long createTime;

  /**消息類型*/
  @XStreamAlias("MsgType")
  @XStreamConverter(value = XStreamCDataConverter.class)
  protected String msgType;

  @XStreamAlias("response")
  protected Response response;

  @XStreamAlias("sign")
  protected String sign;

  @XStreamAlias("sign_type")
  protected String signType;

  /**
   * 獲得ack builder
   * @return
   */
  public static AckBuilder ACK() {
    return new AckBuilder();
  }



  @SuppressWarnings("unchecked")
  public String toXml() {
    StringBuilder builder = new StringBuilder();
    String xml = XStreamTransformer.toXml((Class<AlipayXmlOutMessage>) this.getClass(), this);
    builder.append("<?xml version="1.0" encoding="gbk"?>n");
    builder.append(xml);
    return builder.toString();
  }

}

3.XStreamCDataConverter

package com.milo.xstream.xml;

import com.thoughtworks.xstream.converters.basic.StringConverter;
/**
 * 自定義轉換器
 * @author milogenius
 * @date 2020/4/4 10:56
 *
 */
public class XStreamCDataConverter extends StringConverter {

  @Override
  public String toString(Object obj) {
    return "<![CDATA[" + super.toString(obj) + "]]>";
  }

}

相關注解說明

@XStreamAlias用於定義XStream類或字段別名的註釋

@XStreamConverter用於聲明轉換器的註釋

3.4 測試

XmlDemoTest

package com.milo.xstream;

import com.milo.xstream.outxml.AlipayXmlOutMessage;
import com.milo.xstream.xml.AlipayXmlMessage;

/**
 * @author milogenius
 * @date 2020-04-04 11:49
 */
public class XmlDemoTest {

    public static void main(String[] args) {
        //xml --->pojo
        String bizContent = "<XML>n" +
                "    <AppId><![CDATA[2014070100171523]]></AppId>n" +
                "    <FromUserId><![CDATA[20882837462837462837462837461234]]></FromUserId>n" +
                "    <FromAlipayUserId><![CDATA[2088283746283746]]></FromAlipayUserId>n" +
                "    <CreateTime><![CDATA[1405943673657]]></CreateTime>n" +
                "    <MsgType><![CDATA[event]]></MsgType>n" +
                "    <EventType><![CDATA[follow]]></EventType>n" +
                "    <ActionParam><![CDATA[{"scene":{"sceneId": "1234"}}]]></ActionParam>n" +
                "    <AgreementId><![CDATA[]]></AgreementId>n" +
                "    <AccountNo><![CDATA[]]></AccountNo>n" +
                "    <UserInfo><![CDATA[{"logon_id":"135****1009","user_name":"*iuxu527"}]]></UserInfo>n" +
                "</XML>";
        AlipayXmlMessage alipayXmlMessage = AlipayXmlMessage.fromXml(bizContent);
       // System.out.println(alipayXmlMessage);



        //pojo --->xml
        AlipayXmlOutMessage mpXmlOutMessage = AlipayXmlOutMessage.ACK().toUserId("123456").appId("99999999").build();
        String xml = mpXmlOutMessage.toXml();
        System.out.println(xml);

    }
}

3.5測試結果

3.5.1 xml ---->pojo

輕鬆搞定XML和對象之間的互轉,就它了!

 

3.5.2 pojo --->xml

輕鬆搞定XML和對象之間的互轉,就它了!

 

四.總結

通過上面的一些小案例,高質量編程視頻shangyepingtai.xin 我們學習Xstream的基本用法和註解用法,文章到此爲止,謝謝大家閱讀;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章