Java解析XML的类库很多,本文记录用XStream库对XML的处理
背景
实际开发中,应用报文的格式一般都是JSON和XML;JSON大家都很熟悉(优秀类库:GSON/FastJson/Jackson),但对XML的解析可能并不熟悉,这主要是因为XML一般用于特定的领域:如金融和支付行业等等,想要和银联、网联对接,XML是少不了的
XStream的使用
XStream是解析XML的一款轻量级类库,简单快捷。下面以某银行的交易查询接口为例,讲解XStream对XML的序列化和反序列化的相关使用方法:
报文结构如下:
xml报文结构.png-
创建对应的类(具体类信息添加在文末)
xml对应的model.png -
创建XStream工具类
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class XmlUtil {
/**
*
* @param obj 要序列化的对象
* @return 序列化后的xml字符串
*/
public static String toXml(Object obj) {
XStream xStream = new XStream();
xStream.autodetectAnnotations(true); // 自动发现注解
try {
return xStream.toXML(obj);
} catch (Exception e) {
throw new RuntimeException("Serialization object to xml error: " + e.getMessage());
}
}
/**
*
* @param is XML字符串的字节流
* @param targetClazz xml反序列化的目标类
* @param <T>
* @return 目标类对象
*/
public static <T> T fromXml(InputStream is, Class<T> targetClazz) {
XStream xStream = new XStream();
// 设置安全模式
XStream.setupDefaultSecurity(xStream);
// 允许反序列化的类
xStream.allowTypes(new Class[] {TransStatusInquiryResponse.class});
xStream.processAnnotations(targetClazz); // 反序列化的类
try {
return (T) xStream.fromXML(is);
} catch (Exception e) {
throw new RuntimeException("Deserialization from xml to object error: " + e.getMessage());
}
}
}
- 测试序列化和反序列化的结果
public class Test {
public static final String XML_NS = "name_space_string";
public static final String ISO_DATE_TIME = "yyyy-MM-dd'T'HH:mm:ss";
public static final String responseXml = "<root xmlns=\"name_space_string\">\n" +
" <MsgHeader>\n" +
" <MsgTp>epcc.302.001.01</MsgTp>\n" +
" <IssrId>ICBC00001</IssrId>\n" +
" <Drctn>21</Drctn>\n" +
" <SignSN>87654321</SignSN>\n" +
" <NcrptnSN></NcrptnSN>\n" +
" <DgtlEnvlp></DgtlEnvlp>\n" +
" </MsgHeader>\n" +
" <MsgBody>\n" +
" <SysRtnInf>\n" +
" <SysRtnCd>00000000</SysRtnCd>\n" +
" <SysRtnDesc></SysRtnDesc>\n" +
" <SysRtnTm>2020-11-29T15:41:15</SysRtnTm>\n" +
" </SysRtnInf>\n" +
" <BizInf>\n" +
" <RPFlg>foo</RPFlg>\n" +
" <OriSysRtnCd>foo</OriSysRtnCd>\n" +
" <OriSysRtnDesc>foo</OriSysRtnDesc>\n" +
" <OriBizstsCd></OriBizstsCd>\n" +
" <OriBizStsDesc></OriBizStsDesc>\n" +
" <OriTrxctgy>0115</OriTrxctgy>\n" +
" <OriTrxId>20201128888888888888888800022</OriTrxId>\n" +
" <OriTrxStatus>foo</OriTrxStatus>\n" +
" <DbtrBankId>foo</DbtrBankId>\n" +
" <CdtrBankId>foo</CdtrBankId>\n" +
" <OriTrxAmt>foo</OriTrxAmt>\n" +
" <OriBatchId>foo</OriBatchId>\n" +
" <OriSgnNo>foo</OriSgnNo>\n" +
" <PyerAcctTp>foo</PyerAcctTp>\n" +
" <PyerAcctId>foo</PyerAcctId>\n" +
" <PyerAcctNm>foo</PyerAcctNm>\n" +
" <AcctshrtId>foo</AcctshrtId>\n" +
" <ResfdAcctshrtId>foo</ResfdAcctshrtId>\n" +
" </BizInf>\n" +
" </MsgBody>\n" +
"</root>";
public static void main(String[] args) {
String xmlStr = XmlUtil.toXml(buildRequestObj());
System.out.println(xmlStr);
System.out.println("--------------------------");
TransStatusInquiryResponse inquiryResponse = XmlUtil.fromXml(new ByteArrayInputStream(responseXml.getBytes(StandardCharsets.UTF_8)), TransStatusInquiryResponse.class);
System.out.println(inquiryResponse.toString());
}
private static TransStatusInquiryRequest buildRequestObj() {
TransStatusInquiryRequest inquiryRequest = new TransStatusInquiryRequest();
inquiryRequest.setXmlns(XML_NS);
MsgRequestHeader requestHeader = new MsgRequestHeader();
requestHeader.setSndDt(DateTimeFormatter.ofPattern(ISO_DATE_TIME).format(LocalDateTime.now()));
requestHeader.setMsgTp("epcc.301.001.01");
requestHeader.setIssrId("ICBC00001");
requestHeader.setDrctn("11");
requestHeader.setSignSn("12345678");
requestHeader.setNcrptnSn("");
requestHeader.setDgtlEnvlp("");
inquiryRequest.setMsgRequestHeader(requestHeader);
MsgRequestBody requestBody = new MsgRequestBody();
requestBody.setInstgId("12345678901234");
requestBody.setRPFlg("2");
OriginTrxInfo originTrxInfo = new OriginTrxInfo();
originTrxInfo.setOriTrxCtgy("0115");
originTrxInfo.setOriTrxId("20201128888888888888888800022");
originTrxInfo.setOriTrxDtTm(DateTimeFormatter.ofPattern(ISO_DATE_TIME).format(LocalDateTime.now()));
originTrxInfo.setOriAcctTp("00");
originTrxInfo.setOrisgnNo("");
requestBody.setOriginTrxInfo(originTrxInfo);
inquiryRequest.setMsgRequestBody(requestBody);
return inquiryRequest;
}
}
结果如下:
序列化,组装交易查询的请求报文:
<root xmlns="name_space_string">
<MsgHeader>
<SndDt>2020-11-29T15:46:55</SndDt>
<MsgTp>epcc.301.001.01</MsgTp>
<IssrId>ICBC00001</IssrId>
<Drctn>11</Drctn>
<SignSN>12345678</SignSN>
<NcrptnSN></NcrptnSN>
<DgtlEnvlp></DgtlEnvlp>
</MsgHeader>
<MsgBody>
<InstgId>12345678901234</InstgId>
<RPFlg>2</RPFlg>
<OriTrxInf>
<OriTrxCtgy>0115</OriTrxCtgy>
<OriTrxId>20201128888888888888888800022</OriTrxId>
<OriTrxDtTm>2020-11-29T15:46:55</OriTrxDtTm>
<OriAcctTp>00</OriAcctTp>
<OrisgnNo></OrisgnNo>
</OriTrxInf>
</MsgBody>
</root>
--------------------------
反序列化响应报文,结果如下:
TransStatusInquiryResponse(xmlns=name_space_string, msgResponseHeader=MsgResponseHeader(sndDt=null, msgTp=epcc.302.001.01, issrId=ICBC00001, drctn=21, signSn=87654321, ncrptnSn=, dgtlEnvlp=), msgResponseBody=MsgResponseBody(sysRtnInf=SysRtnInf(sysRtnCd=00000000, sysRtnDesc=, sysRtnTm=2020-11-29T15:41:15), bizInf=BizInf(rPFlg=foo, oriSysRtnCd=foo, oriSysRtnDesc=foo, oriBizstsCd=, oriBizStsDesc=, oriTrxctgy=0115, oriTrxId=20201128888888888888888800022, oriTrxStatus=foo, dbtrBankId=foo, cdtrBankId=foo, oriTrxAmt=foo, oriBatchId=foo, oriSgnNo=foo, pyerAcctTp=foo, pyerAcctId=foo, pyerAcctNm=foo, acctshrtId=foo, resfdAcctshrtId=foo)))
请求报文相关的类信息如下:
@Getter
@Setter
@ToString
@XStreamAlias("root") // 对应的XML中的标签名字
public class TransStatusInquiryRequest {
@XStreamAlias("xmlns") // 对应的XML中的标签名字
@XStreamAsAttribute // 声明root标签的属性
private String xmlns;
@XStreamAlias("MsgHeader") // 对应的XML中的标签名字
private MsgRequestHeader msgRequestHeader;
@XStreamAlias("MsgBody") // 对应的XML中的标签名字
private MsgRequestBody msgRequestBody;
}
@Getter
@Setter
@ToString
@XStreamAlias("MsgHeader")
public class MsgRequestHeader {
@XStreamAlias("SndDt")
private String sndDt;
@XStreamAlias("MsgTp")
private String msgTp;
@XStreamAlias("IssrId")
private String issrId;
@XStreamAlias("Drctn")
private String drctn;
@XStreamAlias("SignSN")
private String signSn;
@XStreamAlias("NcrptnSN")
private String ncrptnSn;
@XStreamAlias("DgtlEnvlp")
private String dgtlEnvlp;
}
@Getter
@Setter
@ToString
@XStreamAlias("MsgBody")
public class MsgRequestBody {
@XStreamAlias("InstgId")
private String instgId;
@XStreamAlias("RPFlg")
private String rPFlg;
@XStreamAlias("OriTrxInf")
private OriginTrxInfo originTrxInfo;
}
@Getter
@Setter
@ToString
@XStreamAlias("OriTrxInf")
public class OriginTrxInfo {
@XStreamAlias("OriTrxCtgy")
private String oriTrxCtgy;
@XStreamAlias("OriTrxId")
private String oriTrxId;
@XStreamAlias("OriTrxDtTm")
private String oriTrxDtTm;
@XStreamAlias("OriAcctTp")
private String oriAcctTp;
@XStreamAlias("OrisgnNo")
private String orisgnNo;
}
响应报文对应的类信息如下:
@Getter
@Setter
@ToString
@XStreamAlias("root")
public class TransStatusInquiryResponse {
// 对响应报文的校验可以使用Java Validation相关注解,非常方便
@XStreamAlias("xmlns")
@XStreamAsAttribute
private String xmlns;
@XStreamAlias("MsgHeader")
private MsgResponseHeader msgResponseHeader;
@XStreamAlias("MsgBody")
private MsgResponseBody msgResponseBody;
}
@Getter
@Setter
@ToString
@XStreamAlias("MsgHeader")
public class MsgResponseHeader {
@XStreamAlias("SndDt")
private String sndDt;
@XStreamAlias("MsgTp")
private String msgTp;
@XStreamAlias("IssrId")
private String issrId;
@XStreamAlias("Drctn")
private String drctn;
@XStreamAlias("SignSN")
private String signSn;
@XStreamAlias("NcrptnSN")
private String ncrptnSn;
@XStreamAlias("DgtlEnvlp")
private String dgtlEnvlp;
}
@Getter
@Setter
@ToString
@XStreamAlias("MsgBody")
public class MsgResponseBody {
@XStreamAlias("SysRtnInf")
private SysRtnInf sysRtnInf;
@XStreamAlias("BizInf")
private BizInf bizInf;
}
@Getter
@Setter
@ToString
@XStreamAlias("SysRtnInf")
public class SysRtnInf {
@XStreamAlias("SysRtnCd")
private String sysRtnCd;
@XStreamAlias("SysRtnDesc")
private String sysRtnDesc;
@XStreamAlias("SysRtnTm")
private String sysRtnTm;
}
@Getter
@Setter
@ToString
@XStreamAlias("BizInf")
public class BizInf {
@XStreamAlias("RPFlg")
private String rPFlg;
@XStreamAlias("OriSysRtnCd")
private String oriSysRtnCd;
@XStreamAlias("OriSysRtnDesc")
private String oriSysRtnDesc;
@XStreamAlias("OriBizstsCd")
private String oriBizstsCd;
@XStreamAlias("OriBizStsDesc")
private String oriBizStsDesc;
@XStreamAlias("OriTrxctgy")
private String oriTrxctgy;
@XStreamAlias("OriTrxId")
private String oriTrxId;
@XStreamAlias("OriTrxStatus")
private String oriTrxStatus;
@XStreamAlias("DbtrBankId")
private String dbtrBankId;
@XStreamAlias("CdtrBankId")
private String cdtrBankId;
@XStreamAlias("OriTrxAmt")
private String oriTrxAmt;
@XStreamAlias("OriBatchId")
private String oriBatchId;
@XStreamAlias("OriSgnNo")
private String oriSgnNo;
@XStreamAlias("PyerAcctTp")
private String pyerAcctTp;
@XStreamAlias("PyerAcctId")
private String pyerAcctId;
@XStreamAlias("PyerAcctNm")
private String pyerAcctNm;
@XStreamAlias("AcctshrtId")
private String acctshrtId;
@XStreamAlias("ResfdAcctshrtId")
private String resfdAcctshrtId;
}
OK, 回聊~
网友评论