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();
}