发一个刚参加工作时候写的利用dom4j把JavaBean转换为XML的工具类,现在看起来有些地方有些笨拙了,并且xml并不是特别的符合XML的规范,只是做为一般的数据载体使用。功能实现主要是利用反射机制和递归。
代码:
import java.lang.reflect.Field;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
/**
*
*
* @version v1.0
* date: 2008-04-24
*/
public class Beans2Xml {
/**
* 返回处理后的结果,如果需要处理请在子类里面重载此方法
*
* @param propertyName
* 属性名称
* @param value
* 属性值,传的是object类型到应用中自己在进行处理/转换为相应的数值类型
* @return 返回处理后的结果,如果为null则删除文档此节点
*/
public String propertyHandler(String propertyName, Object value){
return null;
}
/**
* 此方法用来解决实体中还有实体set或者实体属性,用递归来实现
*
* @param obj
* 要生成XML的实体对象
* @param customSet
* 用于用户自己自定义要处理的实体属性,例如不需要生成某项或者要对某项进行特出的处理都需要放到此SET里面如果没有需要处理的传入new
* set()
* @param beanType
* 用于实体里面有属性为其他实体的时候,需要传入包名进行判断属性是不是实体例如(com.xxx)传如前两个即可。如实体里面只有简单的java元数据类型此参数请传入null
* @param element
* 节点元素
* @param partent
* 用于判断关联关系,例如主单里面有明细,明细里面又有主单的属性
* @return 生成的XML文档
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InstantiationException
* @throws Exception
*/
protected void objectRecursion(Object obj, Set<String> customSet,String beanType, Element element, String partent)
throws IllegalArgumentException, IllegalAccessException {
Class classType = obj.getClass();
Field[] fileds = classType.getDeclaredFields();// 得到实体的所有属性
String entityName = classType.getSimpleName();
Element entityElement = element.addElement(entityName);
Element cellElement = null;
for (int i = 0; i < fileds.length; i++) {
Field field = fileds[i];
field.setAccessible(true);// 设置private的属性值可以读取
String fieldName = field.getName();
cellElement = entityElement.addElement("cell");
cellElement.addAttribute("name", fieldName);
Object value = field.get(obj);
if (!customSet.contains(fieldName)) {
if (value != null) {
String tempType = field.getType().getCanonicalName();
if (beanType == null||(!tempType.startsWith(beanType))) {//只要不是自定义的属性类型都走此过程
if (value instanceof Date) {
if (!(value instanceof Time)) {
cellElement.addText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(value));
} else {
cellElement.addText(new SimpleDateFormat("HH:mm:ss").format(value));
}
} else if (value instanceof List) {// 若为list类型装换为一个以‘,’分隔的字符串
StringBuffer tempString = new StringBuffer();
List tempList = (List) value;
for (int j = 0; j < tempList.size(); j++) {
tempString.append(tempList.get(j) + ",");
}
cellElement.addText(tempString.toString());
} else if (value instanceof Set) {
Set tempSet = (Set) value;
Element setElement =entityElement.addElement(fieldName);
//此方法只处理自己定义的类型,若为元数据类型或者其他更复杂的set类型请自己进行处理
for (Iterator iter = tempSet.iterator(); iter.hasNext();) {
Object object = (Object) iter.next();
partent = classType.getName();// 给出包含set集的实体类型防止出现死循环(一旦set实体里面的属性有实体类型,就会出现死循环,最常见的是关联的时候)
objectRecursion(object, customSet, beanType,setElement, partent);
}
cellElement.detach();//删除具有set属性的元素,因现在它已经变成一个节点
} else {
cellElement.addText(value.toString());
}
} else {
if (beanType != null && tempType.startsWith(beanType)) {
if (tempType.equals(partent))
continue;//防止关联出现死循环
objectRecursion(value, customSet, beanType,entityElement, partent);
}
}
} else {
cellElement.addText("");
}
} else {
if (value != null) {
String reValue = propertyHandler(fieldName, value);
if (reValue == null) {
cellElement.detach();
} else {
cellElement.addText(propertyHandler(fieldName, value));
}
} else {
cellElement.addText("");
}
}
}
}
/**
* 此方法生成一个以实体的名字为节点,节点下面的元素name为实体属性,内容为实体的value的XML文档
*
* @param headMap
* 用户自己定义的XML属性,要以map的方式处理key=属性名称 value=属性值
* @param obj
* 要生成XML的实体对象
* @param customSet
* 用于用户自己自定义要处理的实体属性,例如不需要生成某项或者要对某项进行特出的处理都需要放到此SET里面如果没有需要处理的传入new
* set()
* @param beanType
* 用于实体里面有属性为其他实体的时候,需要传入包名进行判断属性是不是自定义类型(实体)例如(com.xxx)传如前两个即可。如实体里面只有简单的java元数据类型此参数请传入null
* @return 生成的XML文档
*/
public String entityXmlAssembler(Map headMap, Object obj,Set<String> customSet, String beanType) {
Document document = DocumentHelper.createDocument();
Element rootElement = document.addElement("root");// 创建以root命名的根节点
Element headElement = rootElement.addElement("head");// 属性头节点
Element propertyElement = null;
// 生成用户自定义的XML属性
for (Iterator iterator = headMap.keySet().iterator(); iterator.hasNext();) {
propertyElement = headElement.addElement("property");// 属性节点
String propertyString = (String) iterator.next();
propertyElement.addAttribute("name", propertyString);
propertyElement.addText(headMap.get(propertyString).toString());
}
Element bodyElement = rootElement.addElement("body");
try {
this.objectRecursion(obj, customSet, beanType, bodyElement, "");//第一次进行递归无需关联关系
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
document.setXMLEncoding("gb2312");
return document.asXML();
}
}
里面的beanType是完全可以去掉的,代码还能写的更优雅一些,现在懒的在修改了,贴出来以供参考。