前言

在微信订阅号和支付宝生活号日常开发中,我们会涉及到对象和XML之间的相互转换。


java 字符串xml 美化 java字符串转xml_XML


比如我们可以利用StringBuilder去直接拼接来构造XML

/**     * 构造基础的响应消息     *      * @return     */    public static String buildBaseAckMsg(String fromUserId) {        StringBuilder sb = new StringBuilder();        sb.append("");        sb.append("");        sb.append("");        sb.append("" + Calendar.getInstance().getTimeInMillis() + "");        sb.append("");        sb.append("");        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

引入依赖

com.thoughtworks.xstream    xstream    1.4.10

要使用 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);


java 字符串xml 美化 java字符串转xml_支付宝_02


现在,为了使 XStream 输出的 XML 更简洁,可以为 XML 元素名的自定义类名创建别名。这是使用 XStream 所需的惟一映射类型,当然这是可选的。

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

我们会发现XML变得更简洁


java 字符串xml 美化 java字符串转xml_XML_03


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" ?>Joemilo1231234-456123999-456";        Person o = (Person)xstream.fromXML(xmldemo);        System.out.println(o.toString());
123
123


java 字符串xml 美化 java字符串转xml_操作xml字符串_04



三.高级入门

在高级入门中,我们以支付宝生活号开发为例,采用Xstream的注解开发来完成事件订阅过程中的xml报文相关的操作

3.1 项目搭建

首先我们搭建项目springboot-xstream,当然你可以在

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

找到源代码,案例位于springboot-xstream模块下面。由于案例代码太多,强烈建议大家下载源代码案例自己跑一跑。


java 字符串xml 美化 java字符串转xml_XML_05


3.2 相关类解释


java 字符串xml 美化 java字符串转xml_XML_06


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 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")@Datapublic 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) this.getClass(), this);    builder.append("<?xml  version="1.0" encoding="gbk"?>");    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 "";  }}

相关注解说明

@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 = "" +                "    " +                "    " +                "    " +                "    " +                "    " +                "    " +                "    " +                "    " +                "    " +                "    " +                "";        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


java 字符串xml 美化 java字符串转xml_XML_07


3.5.2 pojo --->xml


java 字符串xml 美化 java字符串转xml_java 字符串xml 美化_08


四.总结

通过上面的一些小案例,我们学习Xstream的基本用法和注解用法,文章到此为止,谢谢大家阅读;