利用反射机制JavaBean转换为XML

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值