发一个刚参加工作时候写的利用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是完全可以去掉的,代码还能写的更优雅一些,现在懒的在修改了,贴出来以供参考。