关于JavaBean转XML格式的字符串,目前有很多集成的技术像DOM技术、JAXB技术等,尤其是JAXB的功能简单而强大,只需要几个注解就能够把任何一个实体转为指定的XML格式,方便的不要不要的。本人在做银行报文组装的时候刚开始也这么做,后来发现这么做并没想象中的省事,因为想要组成什么样结构的报文完全体现在我们封装的实体对象内,而很多时候我们业务是杂碎多变的,可能要东拼西凑,需要这个对象的某些字段,那个对象的某些字段,另外,某些枚举对象没写无参构造器,而Marshaller接口在将Java对象序列化为XML数据时必须访问对象的无参构造器,有时候就是这么操蛋,业务上不支持只能想其他办法了。基于以上的业务场景,使用JAXB这种系统集成的技术实现起来反而显得更复杂,不如直接自己拼字符串快,写一个统一的工具类,然后拼报文时候调用就可以,很简单实用。思路是把需要的字段放Map里,用linkedHashMap实现,键充当元素,值充当元素对应的值。以下是本人实际工作写的一个报文接口测试实例。
工具类
package com.nstc.gdms.blogger;
import java.util.List;
/**
*
* description JavaBeanToStringXML
* @author SWX
* date 2016-12-22
*/
public class ToXMLString {
/**
* 合成Element 比如:
* <元素1>值1</元素1>
* <元素2>值2</元素2>
* <元素3>值3</元素3>
* @return StringBuilder
* TIME 下午03:04:11
*/
public static StringBuilder getElement(Map<String, String> map){
StringBuilder stringBuilder = new StringBuilder();
int index = 0, size = map.size();
for (String key : map.keySet()) {
index += 1;
stringBuilder.append("<" + key + ">" + (String)map.get(key) + "</" + key + ">");
if (index < size) {
stringBuilder.append("\r\n");
}
}
return stringBuilder;
}
/**
* 合成RootElement 比如:
* <元素>
* <元素1>值1</元素1>
* <元素2>值2</元素2>
* <元素3>值3</元素3>
* </元素>
* @return StringBuilder
* TIME 下午03:04:11
*/
public static StringBuilder getRootElement(Map<String, String> map, String str) {
StringBuilder stringBuilder = new StringBuilder();
int index = 0, size = map.size();
stringBuilder.append("<").append(str).append(">").append("\r\n");
for (String key : map.keySet()) {
index += 1;
stringBuilder.append("\t").append("<" + key + ">" + (String)map.get(key) + "</" + key + ">");
if (index < size) {
stringBuilder.append("\r\n");
}
}
stringBuilder.append("\r\n").append("<").append("/").append(str).append(">");
return stringBuilder;
}
/**
* 合成带角标的RootElement 比如:
* <元素>
* <index>1</index>
* <元素1>值1</元素1>
* <元素2>值2</元素2>
* <元素3>值3</元素3>
* </元素>
* @return StringBuilder
* TIME 下午03:04:11
*/
public static StringBuilder getRootElement(Map<String, String> map, String str, int in) {
StringBuilder stringBuilder = new StringBuilder();
int index = 0, size = map.size();
stringBuilder.append("<").append(str).append(">").append("\r\n").append("\t").append("<index>" + in + "</index>").append("\r\n");
for (String key : map.keySet()) {
index += 1;
stringBuilder.append("\t").append("<" + key + ">" + (String)map.get(key) + "</" + key + ">");
if (index < size) {
stringBuilder.append("\r\n");
}
}
stringBuilder.append("\r\n").append("<").append("/").append(str).append(">");
return stringBuilder;
}
/**
* 合成RootElementList 比如:
* <list>
* <元素>
* <index>1</index>
* <元素1>值1</元素1>
* <元素2>值2</元素2>
* <元素3>值3</元素3>
* </元素>
* <元素>
* <index>2</index>
* <元素1>值1</元素1>
* <元素2>值2</元素2>
* <元素3>值3</元素3>
* </元素>
* <元素>
* <index>3</index>
* <元素1>值1</元素1>
* <元素2>值2</元素2>
* <元素3>值3</元素3>
* </元素>
* </list>
* @return StringBuilder
* TIME 下午03:04:11
*/
public static StringBuilder getListRootElement(List<String> lt) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<list>").append("\r\n");
int num = lt.size();
for (int i = 0; i < num; i++) {
stringBuilder.append(getMultiLineIndention((String)lt.get(i)));
if (i < num - 1) {
stringBuilder.append("\r\n");
}
}
stringBuilder.append("\r\n").append("</list>");
return stringBuilder;
}
/**
* 给RootElement再添加上跟节点,添加之前先把RootElement的所有行都缩进
* @return StringBuilder
* TIME 下午05:44:21
*/
public static StringBuilder getRootElement(StringBuilder sb, String str) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<").append(str).append(">").append("\r\n").append(getMultiLineIndention(sb.toString())).append("\r\n").append("</" + str + ">");
return stringBuilder;
}
/**
* 合并两个在业务逻辑上成并列前后关系的StringBuilder
* @return StringBuilder
* TIME 下午05:36:04
*/
public static StringBuilder getElementMerge(StringBuilder sb1, StringBuilder sb2) {
return sb1.append("\r\n").append(sb2);
}
/**
* 合并两个在业务逻辑上成并列前后关系的StringBuilder,然后再给其添加上根节点
* @return StringBuilder
* TIME 下午05:36:04
*/
public static StringBuilder getElementMerge(StringBuilder sb1, StringBuilder sb2, String str){
StringBuilder stringBuilder = new StringBuilder();
String sb3 = getMultiLineIndention(getElementMerge(sb1, sb2).toString());
stringBuilder.append("<").append(str).append(">").append("\r\n").append(sb3).append("\r\n").append("</" + str + ">");
return stringBuilder;
}
/**
* 判断字符串中一共有几行,然后给每一行都缩进
* @return String
* TIME 下午05:51:31
*/
public static String getMultiLineIndention(String str) {
String[] ary = str.split("\r\n");
int num = ary.length;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < num; i++) {
stringBuilder.append("\t").append(ary[i]);
if (i < num - 1) {
stringBuilder.append("\r\n");
}
}
return stringBuilder.toString();
}
/**
* 将String转为StringBuilder
* @return StringBuilder
* TIME 下午05:57:53
*/
public static StringBuilder stringToStringBuilder(String str) {
StringBuilder stringBuilder = new StringBuilder();
return stringBuilder.append(str);
}
}
测试类
package com.nstc.gdms.blogger;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
public class ToXMLStringTest {
/**
* H1 /request/head/transCode 交易代码 必输项 字符 10 QBPI
H2 /request/head/transDate 交易日期 必输项 字符 8 资金业务系统产生的交易日期,格式是yyyyMMdd
H3 /request/head/transTime 交易时间 必输项 字符 12 资金业务系统产生的交易时间,格式如HHmmssSSS,精确到毫秒;
H4 /request/head/packetId 指令包序列号 必输项 字符 35 资金业务系统产生的指令包序列号,不能重复;
H5 /request/head/corporationCode 企业客户代码 必输项 字符 资金业务系统输入
H6 /request/head/reserved1 备用字段1 选输项 字符 200
H7 /request/head/reserved2 备用字段2 选输项 字符 200
H8 /request/head/reserved3 备用字段3 选输项 字符 200
H9 /request/head/reserved4 备用字段4 选输项 字符 200
H10 /request/head/reserved5 备用字段5 选输项 字符 2000
D1 /request/body/BillTx/id 指令ID 必输项 数字 12
D2 /request/body/BillTx/frontNodeId 通讯时使用的节点ID 必输项 字符 10 通讯时使用的节点ID
D3 /request/body/BillTx/submitter/openBank/bankNo 所属银行系统 必输项 字符 6
D4 /request/body/BillTx/submitter/nodeNumber 预定义的通讯节点编号 必输项 字符 10
D5 /request/body/BillTx/submitter/number 出票人账户代号 必输项 字符 32 账户代号,最大32位
D6 /request/body/BillTx/list/BillInfo/index 小序号 选输项 字符 4 小序号,4位
D7 /request/body/BillTx/list/BillInfo/billNo 票据编号 必输项 字符 30 票据号码,30位
D8 /request/body/BillTx/list/BillInfo/amount 票面金额 选输项 数字 17 票据金额,17位(15整数位,2小数位)
D9 /request/body/BillTx/reserved1 备用字段1 选输项 字符 200
D10 /request/body/BillTx/reserved2 备用字段2 选输项 字符 200
D11 /request/body/BillTx/reserved3 备用字段3 选输项 字符 200
D12 /request/body/BillTx/reserved4 备用字段4 选输项 字符 200
D13 /request/body/BillTx/reserved5 备用字段5 选输项 字符 2000
*/
@Test
public void test() {
StringBuilder sb = new StringBuilder(128);
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append("\r\n");
sb.append(getRequest().toString());
System.out.println(sb);
}
public static StringBuilder getHead(){
Map<String,String> map = new LinkedHashMap<String, String>();
map.put("transCode", "QBPI");
map.put("transDate", "20161227");
map.put("transTime", "141830999");
map.put("packetId", "18401204935");
map.put("corporationCode", "3528456546");
return ToXMLString.getRootElement(map,"head");
}
public static StringBuilder getBefore(){
Map<String,String> map = new LinkedHashMap<String, String>();
map.put("id", "201");
map.put("frontNodeId", "215651655");
return ToXMLString.getElement(map);
}
public static StringBuilder getSubmitter(){
Map<String,String> map = new LinkedHashMap<String, String>();
map.put("bankNo", "15632");
StringBuilder stringBuilder = ToXMLString.getRootElement(map,"openBank");
map.clear();
map.put("nodeNumber", "215651655");
map.put("number", "153556");
stringBuilder = ToXMLString.getElementMerge(stringBuilder, ToXMLString.getElement(map));
return stringBuilder;
}
public static StringBuilder getBillInfoList(){
Map<String,String> map = new LinkedHashMap<String, String>();
List<String> lt = new ArrayList<String>();
map.put("billNo", "2165");
map.put("amount", "5000000.00");
lt.add(ToXMLString.getRootElement(map, "BillInfo", 1).toString());
return ToXMLString.getListRootElement(lt);
}
public static StringBuilder getBody(){
StringBuilder stringBuilder = ToXMLString.getElementMerge(getBefore(), getSubmitter());
stringBuilder = ToXMLString.getElementMerge(stringBuilder, getBillInfoList());
stringBuilder = ToXMLString.getRootElement(stringBuilder, "BillTx");
stringBuilder = ToXMLString.getRootElement(stringBuilder, "body");
return stringBuilder;
}
public static StringBuilder getRequest(){
return ToXMLString.getElementMerge(getHead(), getBody(), "request");
}
}
测试结果
<?xml version="1.0" encoding="UTF-8"?>
<request>
<head>
<transCode>QBPI</transCode>
<transDate>20161227</transDate>
<transTime>141830999</transTime>
<packetId>18401204935</packetId>
<corporationCode>3528456546</corporationCode>
</head>
<body>
<BillTx>
<id>201</id>
<frontNodeId>215651655</frontNodeId>
<openBank>
<bankNo>15632</bankNo>
</openBank>
<nodeNumber>215651655</nodeNumber>
<number>153556</number>
<list>
<BillInfo>
<index>1</index>
<billNo>2165</billNo>
<amount>5000000.00</amount>
</BillInfo>
</list>
</BillTx>
</body>
</request>