最近作某电商支付项目外接时,遇到须要传输XML报文的。上网查,问同行,最终选择使用XStream插件。很好很强大。贴上代码总结下。java
下面Demo涉及别名、XML结构、空值处理,仍有不少不完善的地方。能够查阅某老司机的帖子: JAVA bean与XML互转的利器---XStream测试
目标报文格式:this
<Service> <Service_Header> <msg_type>YTISSUE</msg_type> <branch_id>QJS201609201547256567816</branch_id> <order_no>LPE20160919103159</order_no> </Service_Header> <Service_Body> <sign_off_time>Mon Sep 19 19:07:02 CST 2016</sign_off_time> <send_cost>20</send_cost> <order_time>Mon Sep 19 18:56:12 CST 2016</order_time> <order_type>1</order_type> <goods_amount>32.8</goods_amount> <order_amount>32.8</order_amount> <Promotions> </Promotions> <Payments> <payment> <payment_method>余额支付</payment_method> <payment_amount>32.8</payment_amount> </payment> </Payments> <Items> <item> <line_no></line_no> <product_code>0825821001</product_code> <product_name>美国进口 万多福椒盐开心果 168g</product_name> <sale_price>32.8</sale_price> <sale_sum>1</sale_sum> <Payments> <payment> <payment_method>余额支付</payment_method> <payment_amount>32.8</payment_amount> </payment> </Payments> <Promotions> </Promotions> <order_detail_no>LPE201609191031590101</order_detail_no> <payment_method>余额支付:32.8</payment_method> </item> </Items> </Service_Body> </Service>
报文封装类 :.net
package com.iokbl.dto.xml.issue; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 下发ERP报文根节点 * @author tm * @date 2016年9月18日下午1:25:04 */ @XStreamAlias("Service") public class ServiceRootClass { @XStreamAlias("Service_Header") private ServiceHeaderClass header; //报文头 @XStreamAlias("Service_Body") private ServiceBodyClass body; //报文体 public ServiceHeaderClass getHeader() { return header; } public void setHeader(ServiceHeaderClass header) { this.header = header; } public ServiceBodyClass getBody() { return body; } public void setBody(ServiceBodyClass body) { this.body = body; } }
报文头类:插件
package com.iokbl.dto.xml.issue; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * ERP下发报文头结构 * @author tm * @date 2016年9月18日下午1:25:04 */ @XStreamAlias("Service_Header") public class ServiceHeaderClass { @XStreamAlias("msg_type") private String msg_type = ""; //消息类型 @XStreamAlias("branch_id") private String branch_id = ""; //批次号 @XStreamAlias("order_no") private String order_no = ""; //订单号 public String getMsg_type() { return msg_type; } public void setMsg_type(String msg_type) { this.msg_type = msg_type; } public String getBranch_id() { return branch_id; } public void setBranch_id(String branch_id) { this.branch_id = branch_id; } public String getOrder_no() { return order_no; } public void setOrder_no(String order_no) { this.order_no = order_no; } }
报文体父类:code
package com.iokbl.dto.xml.issue; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamImplicit; import com.thoughtworks.xstream.annotations.XStreamImplicitCollection; /** * ERP下发报文头结构 * @author tm * @date 2016年9月18日下午1:25:04 */ @XStreamAlias("Service_Body") public class ServiceBodyClass { @XStreamAlias("sign_off_time") private String sign_off_time = ""; //签收时间 @XStreamAlias("send_cost") private String send_cost = ""; //运费 @XStreamAlias("order_time") private String order_time = ""; //订单下单时间 @XStreamAlias("order_type") private String order_type = ""; //订单类型(见字典) @XStreamAlias("goods_amount") private String goods_amount = ""; //商品总金额(不含运费的订单金额) @XStreamAlias("order_amount") private String order_amount = ""; //订单实际金额(用户实际支付金额,包含运费) @XStreamAlias("Promotions") private List<OrderPromotionIssueDto> promList = new ArrayList<OrderPromotionIssueDto>(); //订单行优惠项明细 @XStreamAlias("Payments") private List<OrderPaymentIssueDto> payList = new ArrayList<OrderPaymentIssueDto>(); //商品支付项明细 @XStreamAlias("Items") private List<ProductBaseIssueDto> itemList = new ArrayList<ProductBaseIssueDto>(); //订单行商品列表 public String getSign_off_time() { return sign_off_time; } public void setSign_off_time(String sign_off_time) { this.sign_off_time = sign_off_time; } public String getSend_cost() { return send_cost; } public void setSend_cost(String send_cost) { this.send_cost = send_cost; } public String getOrder_time() { return order_time; } public void setOrder_time(String order_time) { this.order_time = order_time; } public String getOrder_type() { return order_type; } public void setOrder_type(String order_type) { this.order_type = order_type; } public String getGoods_amount() { return goods_amount; } public void setGoods_amount(String goods_amount) { this.goods_amount = goods_amount; } public String getOrder_amount() { return order_amount; } public void setOrder_amount(String order_amount) { this.order_amount = order_amount; } public List<OrderPromotionIssueDto> getPromList() { return promList; } public void setPromList(List<OrderPromotionIssueDto> promList) { this.promList = promList; } public List<OrderPaymentIssueDto> getPayList() { return payList; } public void setPayList(List<OrderPaymentIssueDto> payList) { this.payList = payList; } public List<ProductBaseIssueDto> getItemList() { return itemList; } public void setItemList(List<ProductBaseIssueDto> itemList) { this.itemList = itemList; } }
报文体--子类(订单优惠信息list):xml
package com.iokbl.dto.xml.issue; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 优惠信息类-订单纬度 * @author tm * @date 2016年9月18日下午2:45:44 */ @XStreamAlias("promotion") public class OrderPromotionIssueDto { @XStreamAlias("promotion_type") private String promotion_type = ""; //优惠类型 @XStreamAlias("coupon_no") private String coupon_no = ""; //优惠券号 @XStreamAlias("promotion_amount") private String promotion_amount = "";//券承担方金额 @XStreamAlias("promotion_entities") private String promotion_entities = "";//券承担方 @XStreamAlias("acitivity_code") private String acitivity_code = ""; //活动编号 @XStreamAlias("acitivity_name") private String acitivity_name = ""; //活动名称 @XStreamAlias("templet_code") private String templet_code = ""; //模板编号 @XStreamAlias("templet_name") private String templet_name = ""; //模板名称 public String getPromotion_type() { return promotion_type; } public void setPromotion_type(String promotion_type) { this.promotion_type = promotion_type; } public String getCoupon_no() { return coupon_no; } public void setCoupon_no(String coupon_no) { this.coupon_no = coupon_no; } public String getPromotion_amount() { return promotion_amount; } public void setPromotion_amount(String promotion_amount) { this.promotion_amount = promotion_amount; } public String getPromotion_entities() { return promotion_entities; } public void setPromotion_entities(String promotion_entities) { this.promotion_entities = promotion_entities; } public String getAcitivity_code() { return acitivity_code; } public void setAcitivity_code(String acitivity_code) { this.acitivity_code = acitivity_code; } public String getAcitivity_name() { return acitivity_name; } public void setAcitivity_name(String acitivity_name) { this.acitivity_name = acitivity_name; } public String getTemplet_code() { return templet_code; } public void setTemplet_code(String templet_code) { this.templet_code = templet_code; } public String getTemplet_name() { return templet_name; } public void setTemplet_name(String templet_name) { this.templet_name = templet_name; } }
报文体--子类(订单支付信息list):对象
package com.iokbl.dto.xml.issue; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 支付信息-订单纬度 * @author tm * @date 2016年9月18日下午2:55:21 */ @XStreamAlias("payment") public class OrderPaymentIssueDto { @XStreamAlias("payment_method") private String payment_method = ""; //支付方式 @XStreamAlias("payment_amount") private String payment_amount = ""; //支付金额 public String getPayment_method() { return payment_method; } public void setPayment_method(String payment_method) { this.payment_method = payment_method; } public String getPayment_amount() { return payment_amount; } public void setPayment_amount(String payment_amount) { this.payment_amount = payment_amount; } }
报文体--子类(订单中某商品的基本信息):blog
package com.iokbl.dto.xml.issue; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 订单行商品明细-商品纬度 * @author tm * @date 2016年9月18日下午2:46:10 */ @XStreamAlias("item") public class ProductBaseIssueDto { @XStreamAlias("line_no") private String line_no = ""; //行编号 @XStreamAlias("product_code") private String product_code = "";//商品编号 @XStreamAlias("product_name") private String product_name = "";//商品名称 @XStreamAlias("sale_price") private String sale_price = ""; //订购价(商品售价) @XStreamAlias("sale_sum") private String sale_sum = ""; //订购量 @XStreamAlias("Payments") private List<ProductPaymentIssueDto> payList; //商品支付项明细 @XStreamAlias("Promotions") private List<ProductPromotionIssueDto> promList; //订单行优惠项明细 public String getLine_no() { return line_no; } public void setLine_no(String line_no) { this.line_no = line_no; } public String getProduct_code() { return product_code; } public void setProduct_code(String product_code) { this.product_code = product_code; } public String getProduct_name() { return product_name; } public void setProduct_name(String product_name) { this.product_name = product_name; } public String getSale_price() { return sale_price; } public void setSale_price(String sale_price) { this.sale_price = sale_price; } public String getSale_sum() { return sale_sum; } public void setSale_sum(String sale_sum) { this.sale_sum = sale_sum; } public List<ProductPaymentIssueDto> getPayList() { return payList; } public void setPayList(List<ProductPaymentIssueDto> payList) { this.payList = payList; } public List<ProductPromotionIssueDto> getPromList() { return promList; } public void setPromList(List<ProductPromotionIssueDto> promList) { this.promList = promList; } }
报文体--子类(订单中某商品的优惠信息list):支付宝
package com.iokbl.dto.xml.issue; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 商品优惠信息类(虽与订单优惠信息结构一致,但组装保文时必须新建该对象才能正常显示指定报文结构。) * @author tm * @date 2016年9月18日下午2:45:44 */ @XStreamAlias("promotion") public class ProductPromotionIssueDto extends OrderPromotionIssueDto{ }
报文体--子类(订单中某商品的支付信息list):
package com.iokbl.dto.xml.issue; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 支付信息(虽与订单支付结构一致,但组装保文时必须新建该对象才能正常显示指定报文结构。) * @author tm * @date 2016年9月18日下午2:55:21 */ @XStreamAlias("payment") public class ProductPaymentIssueDto extends OrderPaymentIssueDto{ }
最终测试类:
package com.iokbl.dto.xml.issue; import java.util.ArrayList; import java.util.List; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder; /** * 测试类 * @author tm * @date 2016年9月18日下午1:42:43 */ public class Test { public static void main(String[] args) { //目标对象 ServiceRootClass root = new ServiceRootClass(); ServiceHeaderClass header = new ServiceHeaderClass(); ServiceBodyClass body = new ServiceBodyClass(); header.setMsg_type("MMMM"); header.setBranch_id("4546"); header.setOrder_no("1111111"); body.setGoods_amount("12"); body.setSign_off_time("2016-07-08 15:30:20"); body.setGoods_amount("10"); body.setOrder_amount("111110001"); body.setOrder_time("2016-07-09 15:30:20"); body.setOrder_type("销售订单"); body.setSend_cost("成本500"); /** 封装优惠信息start **/ OrderPromotionIssueDto prom1 = new OrderPromotionIssueDto(); prom1.setAcitivity_code("100001"); prom1.setAcitivity_name("满200减80"); prom1.setCoupon_no("YHQ1001"); prom1.setPromotion_amount("200"); prom1.setPromotion_entities("YT5201"); prom1.setPromotion_type("满减"); prom1.setTemplet_code("Template1001"); prom1.setTemplet_name("满200减80活动模板"); OrderPromotionIssueDto prom2 = new OrderPromotionIssueDto(); prom2.setAcitivity_code("100002"); prom2.setAcitivity_name("全场八折"); prom2.setCoupon_no("ZKZR1001"); prom2.setPromotion_amount("200"); prom2.setPromotion_entities("YT5201"); prom2.setPromotion_type("折扣折让"); prom2.setTemplet_code("Template1002"); prom2.setTemplet_name("八折模板"); List<OrderPromotionIssueDto> promList = new ArrayList<OrderPromotionIssueDto>(); promList.add(prom1); promList.add(prom2); //封装优惠信息到报文体 body.setPromList(promList); /** 封装优惠信息end **/ /** 封装支付信息start **/ OrderPaymentIssueDto pay = new OrderPaymentIssueDto(); pay.setPayment_method("支付宝"); pay.setPayment_amount("305.00"); List<OrderPaymentIssueDto> payList = new ArrayList<OrderPaymentIssueDto>(); payList.add(pay); body.setPayList(payList); /** 封装支付信息end **/ /** 封装商品行信息start **/ List<ProductPaymentIssueDto> subls = new ArrayList<ProductPaymentIssueDto>() ; ProductPaymentIssueDto sub = new ProductPaymentIssueDto() ; sub.setPayment_amount("4545"); sub.setPayment_method("test"); subls.add(sub) ; List<ProductPromotionIssueDto> subPromList = new ArrayList<ProductPromotionIssueDto>(); ProductPromotionIssueDto subPromDto = new ProductPromotionIssueDto(); subPromDto.setAcitivity_code("100001"); subPromDto.setAcitivity_name("满200减80"); subPromDto.setCoupon_no("YHQ1001"); subPromDto.setPromotion_amount("200"); subPromDto.setPromotion_entities("YT5201"); subPromDto.setPromotion_type("满减"); subPromDto.setTemplet_code("Template1001"); subPromDto.setTemplet_name("满200减80活动模板"); subPromList.add(subPromDto); ProductBaseIssueDto item1 = new ProductBaseIssueDto(); item1.setLine_no("518"); item1.setProduct_code("PRD1001"); item1.setProduct_name("德芙巧克力"); item1.setSale_price("26.40"); item1.setSale_sum("5"); item1.setPromList(subPromList); item1.setPayList(subls); List<ProductBaseIssueDto> itemList = new ArrayList<ProductBaseIssueDto>(); itemList.add(item1); body.setItemList(itemList); /** 封装商品行信息end **/ root.setHeader(header); root.setBody(body); XStream x = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_"))); x.autodetectAnnotations(true); String xml = x.toXML(root); System.out.println(xml); } }
----以上Test.java,亲测有效。
开发期间遇到坑:
一、XStream对空值不输出成对标签,单个值可经过声明时添加默认空值实现,但List为空时,坑还没填上……