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