天天看點

java實體類解析成xml格式的字元串1.背景2.效果預覽

1.背景

因工作需要生成xml格式的字元串,傳到消息隊列與其他服務通訊。如果自己手動string.append則非常繁瑣且不可通用,故寫了個工具類,将一個實體類解析成xml字元串。

2.效果預覽

目标xml格式

<msg>
    <rvHeader>
        <source>
            <application>MES</application>
            <msgBus>Tibrv</msgBus>
            <domain></domain>
            <address></address>
        </source>
        <destination>
            <application>EAP</application>
            <msgBus>Tibrv</msgBus>
            <domain></domain>
            <address>.EAP.></address>
        </destination>
    </rvHeader>
    <msgBody>
        <retMessage/>
        <action>1</action>
        <retCode>1</retCode>
    </msgBody>
</msg>

           

源java代碼

@Data
@XmlTagName("msg")
public class Msg {

    private RvHeader rvHeader;

    private MsgHeader msgHeader;

    private MsgBody msgBody;

    public static Msg newInstance() {
        Msg msg = new Msg();
        msg.rvHeader = new RvHeader();
        msg.msgHeader = new MsgHeader();
        return msg;
    }
    public static Msg newInstance(MsgBody msgBody) {
        Msg msg = new Msg();
        msg.rvHeader = new RvHeader();
        msg.msgHeader = new MsgHeader();
        msg.msgBody = msgBody;
        return msg;
    }
}


@Data
@XmlTagName("rvHeader")
public class RvHeader {

    private Source source;

    private Destination destination;

    public RvHeader() {
        this.source = new Source();
        this.destination = new Destination();
    }

    public static RvHeader newInstance() {
        return new RvHeader();
    }
}


@Data
@XmlTagName("source")
public class Source {

    private String application;

    private String msgBus;

    private String domain;

    private String address;
}

@Data
@XmlTagName("destination")
public class Destination {
    private String application;

    private String msgBus;

    private String domain;

    private String address;
}

@Data
@XmlTagName("msgBody")
public class EAPReqDestinationForZBRequestDto implements MsgBody {
    private String userId;

    private String eqpId;

    private String lotId;

    private String pausePoint;
}

public interface MsgBody {
}

@Documented
@Target({ElementType.TYPE, ElementType.FIELD})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface XmlTagName {
    String value();
}
           

工具類代碼

Msg msg = new Msg();
// todo 設定msg裡面各個類的成員變量屬性。。。代碼省略

// 列印xml格式的字元串
System.out.println(XmlUtils.objectFormat2Xml(msg));
           

XmlUtils

xml的具體的name我設計通過注解來擷取,如果沒有寫注解,則取成員變量的名稱。需要用到反射機制,要引用部分反射的類

import java.lang.reflect.Field;

public static String objectFormat2Xml(Object object) {
        StringBuilder builder = new StringBuilder();
        int spaceCount = 0;
        try {
            XmlUtils.elementFormat(object, builder, spaceCount);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return builder.toString();
    }
public static void elementFormat(Object object, StringBuilder builder, int spaceCount) throws Exception {


        Class<?> classType = object.getClass();
        String objectName = classType.getAnnotation(XmlTagName.class).value(); //擷取對象的屬性名稱
        builder.append(getSpaceStringByCount(spaceCount) + "<" + objectName + ">\n");
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            //擷取f對象對應類中的所有屬性域
            field.setAccessible(true);

            Class<?> type = field.getType();
            XmlTagName annotation = field.getAnnotation(XmlTagName.class);
            String name = annotation == null ? field.getName() : annotation.value(); //擷取對象的屬性名稱
            Object value = field.get(object);//擷取對象的屬性值


            if (String.class.isAssignableFrom(type)) { // 如果是string 則直接拼接值
                if (value == null) {
                    builder.append(getSpaceStringByCount(spaceCount + 4) + "<" + name + "/>\n");
                    continue;
                }
                builder.append(getSpaceStringByCount(spaceCount + 4) + "<" + name + ">").append(value).append("</" + name + ">\n");
                continue;
            }

            if (List.class.isAssignableFrom(type)) { // 如果是List
                List<Object> list = (List<Object>) value;
                if (list.isEmpty()) {
                    builder.append(getSpaceStringByCount(spaceCount + 4) + "<" + name + "/>\n");
                    continue;
                }

                builder.append(getSpaceStringByCount(spaceCount + 4) + "<" + name + ">\n");
                for (Object o : list) {
                    XmlUtils.elementFormat(o, builder, spaceCount + 8);
                }
                builder.append(getSpaceStringByCount(spaceCount + 4) + "</" + name + ">\n");
            } else { // object對象類型
                XmlUtils.elementFormat(value, builder, spaceCount + 4);
            }

        }
        builder.append(getSpaceStringByCount(spaceCount) + "</" + objectName + ">\n");
    }

public static String getSpaceStringByCount(int count) {
        StringBuilder builder = new StringBuilder();
        while (count-- > 0) {
            builder.append(" ");
        }
        return builder.toString();
    }