JavaBean转XML

本文讨论了在Java中使用JAXB进行JavaBean到XML转换时遇到的问题,包括业务需求的灵活性、枚举对象构造器限制等,并提出直接通过自定义工具类拼接XML字符串的简便方法。这种方法适用于业务需求多变且需要灵活组装XML报文的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于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>



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值