最近项目中需要调用webService接口,请求时会传送xml报文,查阅了网上很多资料发现每次不一样的xml格式都需要修改生成xml的方法里的代码,并没有真正的做到通过bean来动态生成xml报文,因此现开发一个不需要修改生成xml的方法来动态生成xml报文(提示:此方法只适合三层嵌套的xml报文,如需更多嵌套则需要进行改进)
1.添加所需的包
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>2.0.2</version>
</dependency>
2.编写能够判断xml层级的标签(可自己随意命名做区分)
- 生成Root标签类,来代表当前bean里的变量哪一个是根节点
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
//这里注意:RetentionPolicy需要手动导包
@Retention(RetentionPolicy.RUNTIME)
public @interface Root {
}
- 生成First标签类,来代表当前bean里的变量哪一个是子节点
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface First {
}
3.编写动态生成xml的代码
import java.util.HashMap;
import java.util.Map;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import com.annotation.First;
import com.annotation.Root;
import com.entity.NodeInfo;
public class BeanToXmlUtil {
/**
* 通过bean自动生成xml(只满足于三层)
* @param t
* @return
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public <T> String beanToXml(T t) throws IllegalArgumentException, IllegalAccessException {
String xml = "";
Element xmlRoot = null;
Class<?> xmlClass = t.getClass();
Map<String,NodeInfo> firstMap = new HashMap<String,NodeInfo>();
for(Field field : xmlClass.getDeclaredFields()){
field.setAccessible(true); // true 能够取到到类中的私有属性,默认为false
if(field.isAnnotationPresent(Root.class)){
xmlRoot = new Element(field.getName());
}
if(field.isAnnotationPresent(First.class)){
NodeInfo nodeInfo = new NodeInfo();
nodeInfo.setParent(xmlRoot.getName());
nodeInfo.setValue(field.get(t));
firstMap.put(field.getName(), nodeInfo);
}
}
for (Map.Entry<String, NodeInfo> entry : firstMap.entrySet()) {
Element element = new Element(entry.getKey());
if(!((entry.getValue().getValue()) instanceof String)){
for(Field fNode : entry.getValue().getValue().getClass().getDeclaredFields()){
fNode.setAccessible(true);
if(fNode.isAnnotationPresent(First.class)){
Element elementNode = new Element(fNode.getName());
elementNode.setText((String) fNode.get(entry.getValue().getValue()));
element.addContent(elementNode);
}
}
}else{
element.setText((String)entry.getValue().getValue());
}
xmlRoot.addContent(element);
}
Document doc = new Document(xmlRoot);
XMLOutputter out = new XMLOutputter();
Format format = Format.getCompactFormat();
format.setEncoding("UTF-8");
format.setIndent("\t");
out.setFormat(format);// 设置文件编码,默认为UTF-8
ByteArrayOutputStream bo = new ByteArrayOutputStream();
try {
out.output(doc, bo);
xml = new String(bo.toByteArray(), "UTF-8");
} catch (Exception e) {
e.printStackTrace();;
}
return xml;
}
}
//记录节点的相关信息
public class NodeInfo {
private Object value;
private String parent;
public String getParent() {
return parent;
}
public void setParent(String parent) {
this.parent = parent;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
4.测试bean
import com.annotation.First;
import com.annotation.Root;
public class TestXml {
@Root
private String Xml;
@First
private UserData userData;
@First
private String ext;
public String getXml() {
return Xml;
}
public void setXml(String xml) {
Xml = xml;
}
public UserData getUserData() {
return userData;
}
public void setUserData(UserData userData) {
this.userData = userData;
}
public String getExt() {
return ext;
}
public void setExt(String ext) {
this.ext = ext;
}
}
import com.annotation.First;
public class UserData {
@First
private String name;
@First
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
5.进行测试
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
TestXml testXml= new TestXml();
UserData userData = new UserData();
userData.setName("xxp");
userData.setAge("18");
testXml.setExt("xxp is 18");
testXml.setUserData(userData);
BeanToXmlUtil.beanToXml(testXml);
}
结果
6.总结
优点:此篇方法能只修改bean上的标签来动态生成xml,无需修改生成xml中的代码
缺点:多层(3层以上)嵌套的问题,需要改进代码,深度大的话要不断的进行遍历