`
easion_zms
  • 浏览: 95431 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类

利用反射机制和DOM4J创建生成XML的通用类

    博客分类:
  • java
阅读更多

最近的项目中用到了XML,所以就写了个对象转换为XML文件的通用类。

package com.creawor.cbsms.client.xml.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * Description: 反射机制工具类,根据传入的Obj,
 *              为生成xml文件提取所有属性和属性对应的值       
 * </p>
 * 
 * 
 * @author Administrator
 * @since  2008-12-1
 * @version
 */
public class ReflectionUtil {

	//所有的系统类型
	private static String[] allSysDefinedType = new String[] {
			"java.lang.String", "java.lang.Long", "long", "java.lang.Integer",
			"int", "java.lang.Short", "short", "java.lang.Byte", "byte",
			"java.lang.Float", "float", "java.lang.Double", "double",
			"java.util.Date", "java.lang,Char", "char", "java.lang.Boolean",
			"boolean", "java.sql.Timestamp" };

	private static String dateFormatString = "yyyy-MM-dd HH:mm:ss";

	//使用不可以是属性名前缀的*作为标识是否是用户自定义的类型
	private static String userDefiendTypePrefix = "*";

	/**
	 * 根据传入的对象将对象的属性和该属性对应的值放入map
	 * @param  obj
	 *           待映射属性和属性值的对象
	 * @param  unReflectProp
	 *           不需要映射属性和属性值的所有属性;
	 *           eg. CbsTargetTime对象中有DATE_FORMAT不需要映射则在该参数中添加
	 *               CbsTargetTime.DATE_FORMAT
	 *  
	 * @return Map
	 *           key = property name ; value = property value;
	 *           (如果属性为一个用户自定义类型的对象那么
	 *           key = '*' + 'user defined type';
	 *           value = map;map中key是属性,value是值,依次循环)
	 */
	public Map<String, Object> transformObjData2Map(Object obj,
			String[] unReflectProp) {
		Map<String, Object> rootMap = new HashMap<String, Object>();
		Map<String, Object> dataMap = new HashMap<String, Object>();
		rootMap.put(userDefiendTypePrefix + obj.getClass().getSimpleName(),
				dataMap); // 使用不可以是属性名前缀的*作为标识是否是用户自定义的类型
		this.getObjPro(obj, unReflectProp, dataMap, obj.getClass().getName());
		return rootMap;
	}

	/**
	 * 得到传入对象的每个属性域,
	 * 根据每个属性域得到属性域对应的值
	 * 
	 * @param obj 
	 *         待映射得到属性和值的对象
	 *         
	 * @param  unReflectProp
	 *         不需要映射属性和属性值的所有属性;
	 *         
	 * @param  className 
	 *         对象的类型名,如果传入对象为空时,用其新建一个对象
	 * @param dataMap
	 *         key=属性,value=属性的值
	 */

	@SuppressWarnings("unchecked")
	private void getObjPro(Object obj, String[] unReflectProp, Map dataMap,
			String className) {
		try {
			Class clas;
			if (obj == null) {
				clas = Class.forName(className);
				obj = clas.newInstance();
			} else {
				clas = Class.forName(obj.getClass().getName());
			}

			//得到obj类的所有属性
			Field[] fileds = clas.getDeclaredFields();
			for (Field field : fileds) {
				String fieldName = field.getName();
				String fieldType = field.getType().getName();
				//如果该属性是不需要映射的属性则跳出循环
				if (!reflectPropOrNot(obj.getClass().getSimpleName() + "."
						+ fieldName, unReflectProp)) {
					continue;
				}
				//属性名的第一个字母大写,与get或者is组成方法名
				String firstCharUpper = fieldName.substring(0, 1).toUpperCase()
						+ fieldName.substring(1, fieldName.length());
				Method method;
				//如果是boolean型则方法名为is*;反之为get*
				if (isBooleanType(fieldType)) {
					method = clas.getMethod("is" + firstCharUpper, null);
				} else {
					method = clas.getMethod("get" + firstCharUpper, null);
				}

				if (isSysDefinedType(fieldType)) {
					//如果是系统类型则添加进入map
					String formatDateStr = isTimeType(fieldType, method, obj);
					if (formatDateStr != null) {
						dataMap.put(fieldName, formatDateStr);
						continue;
					}
					dataMap.put(fieldName,
							method.invoke(obj, null) == null ? "" : method
									.invoke(obj, null));

				} else {
					//如果不是系统类型对象则key = * + 属性名 ; value = map;循环迭代
					Map dateMap2 = new HashMap();
					this.getObjPro(method.invoke(obj, null), unReflectProp,
							dateMap2, fieldType);
					dataMap.put(userDefiendTypePrefix
							+ field.getType().getSimpleName(), dateMap2);
				}

			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("映射属性和属性所对应值出现异常!!");
			e.printStackTrace();

		}

	}

	/**
	 * 验证属性是否是要通过反射机制得到名称和值
	 * @param fieldName
	 *              待验证的属性
	 * @return
	 *        true  要利用反射机制的到属性名和值
	 *        false 不需要利用反射机制的到属性名和值
	 */
	private boolean reflectPropOrNot(String fieldName, String[] unReflectProp) {
		if (unReflectProp == null) {
			return true;
		}
		for (String propName : unReflectProp) {
			if (propName.equals(fieldName)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 验证属性的类型是否是系统定义的类型
	 * @param fieldType
	 *             待验证类型的名称
	 * @return
	 *        true  是系统定义的对象
	 *        false 用户定义的对象
	 */
	private boolean isSysDefinedType(String fieldType) {
		for (String type : allSysDefinedType) {
			if (fieldType.equals(type)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 如果该属性是日期属性则根据要输出的类型返回字符串,反之返回null
	 * @param fileType
	 * @param method
	 * @param obj
	 * @return
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	private String isTimeType(String fileType, Method method, Object obj)
			throws IllegalAccessException, InvocationTargetException {
		if (fileType.equals("java.util.Date")
				|| fileType.equals("java.sql.Timestamp")) {
			if (method.invoke(obj, null) == null) {
				return null;
			}
			SimpleDateFormat sdf = new SimpleDateFormat(dateFormatString);
			return sdf.format(method.invoke(obj, null));
		} else {
			return null;
		}
	}

	public boolean isBooleanType(String fieldType) {
		if (fieldType.equals("java.util.Boolean")
				|| fieldType.equals("boolean")) {
			return true;
		}
		return false;
	}

	public static void setDateFormatString(String dateFormatString) {
		ReflectionUtil.dateFormatString = dateFormatString;
	}

	public static String getUserDefiendTypePrefix() {
		return userDefiendTypePrefix;
	}

	public static void setUserDefiendTypePrefix(String userDefiendTypePrefix) {
		ReflectionUtil.userDefiendTypePrefix = userDefiendTypePrefix;
	}

}

 

 

package com.creawor.cbsms.client.xml.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

/**
 * <p>
 * Description: XML生成类,将传入的对象生成XML文件
 *                  
 * </p>
 * 
 * 
 * @author Administrator
 * @since  2008-12-1
 * @version
 */
public class XMLProcessor {

	private ReflectionUtil reflectionUtil;

	/**
	 * 建立一个XML文档,文档名由输入参数决定
	 * 
	 * @param obj      
	 * @param unReflectProp
	 * @param filename
	 *           
	 * @return 
	 */
	@SuppressWarnings("unchecked")
	public void createXMLFile(List<Object> objs, String[] unReflectProp,
			String filename) throws IndexOutOfBoundsException, IOException {
		reflectionUtil = new ReflectionUtil();
		// 建立Document对象
		Document document = DocumentHelper.createDocument();
		// 添加根节点进入Document
		Element rootElement = document.addElement(objs.get(0).getClass()
				.getSimpleName()
				+ "s");
		for (Object obj : objs) {
			Map<String, Object> rootMap = reflectionUtil.transformObjData2Map(
					obj, unReflectProp);
			String rootString = ReflectionUtil.getUserDefiendTypePrefix()
					+ obj.getClass().getSimpleName();
			map2Node((Map) rootMap.get(rootString), rootElement, rootString);
		}

		// 格式化输出XML,换行缩进
		OutputFormat format = OutputFormat.createPrettyPrint();
		// 设置字符集
		format.setEncoding("GBK");
		// 将document中的内容写入文件中
		XMLWriter writer = new XMLWriter(new FileWriter(new File(filename)),
				format);
		writer.write(document);
		writer.close();

	}

	/**
	 * 将映射为 对象的属性-->属性对应的值 的map转换为xml文件中的各个节点
	 * @param dataMap
	 *            
	 * @param objNode
	 *            父节点,map中创建的节点都是其子节点
	 * @param objClass
	 *            父节点的名称
	 */
	@SuppressWarnings("unchecked")
	private void map2Node(Map<String, Object> dataMap, Element objNode,
			String objName) {
		//第一个字符是*,创建*后面字符为名称的节点
		Element objElement = objNode.addElement(objName.substring(1));
		if (isAllSysType(dataMap)) {
			//如果该对象中全部是系统类型则全部添加到objElement节点下
			for (String propName : dataMap.keySet()) {
				createNextNode(objElement, propName, dataMap.get(propName) + "");
			}

		} else {
			//如果该对象中还有用户自定义类型则系统类型添加进入  objNameInfo节点下,用户自定义类型添加进入 自定义类型名成节点下
			Element infoNode = objElement.addElement(objName.substring(1)
					+ "Info");

			for (String propName : dataMap.keySet()) {
				if (propName.startsWith("*")) {
					map2Node((Map) dataMap.get(propName), objElement, propName);
				} else {
					createNextNode(infoNode, propName, dataMap.get(propName)
							+ "");
				}

			}
		}
	}

	/**
	 * 根据name和text创建elements的子节点
	 * 
	 * @param element
	 * @param nodeName
	 * @param text
	 */
	private void createNextNode(Element element, String nodeName, String text) {
		Element nextElement = element.addElement(nodeName);
		if (text == null) {
			return;
		}
		nextElement.setText(text);
	}

	/**
	 * 是否是系统类,如果前缀是*则是自定义类型
	 * @param dataMap
	 * @return
	 */
	private boolean isAllSysType(Map<String, Object> dataMap) {

		for (String propName : dataMap.keySet()) {
			if (propName.startsWith("*")) {
				return false;
			}
		}
		return true;
	}

	public ReflectionUtil getReflectionUtil() {
		return reflectionUtil;
	}

	public void setReflectionUtil(ReflectionUtil reflectionUtil) {
		this.reflectionUtil = reflectionUtil;
	}

}

 

package com.creawor.cbsms.client.xml.service;

import java.io.IOException;
import java.util.List;

import com.creawor.cbsms.client.xml.util.XMLProcessor;

/**
 * <p>
 * Description: 提供对象转换为XML的调用接口
 *                  
 * </p>
 * 
 * 
 * @author Administrator
 * @since  2008-12-2
 * @version
 */
public class Object2XMLHander {

	private XMLProcessor xmlProcessor;

	/**
	 * 生成一个XML文档,文档名由输入参数决定
	 * 
	 * @param objs
	 *          待转换为XML文件的对象集合
	 *          
	 * @param unReflectProp
	 *           不需要映射进入XML属性;如果全部要映射进入XML文件则传入null
	 *           eg. CbsTargetTime对象中有DATE_FORMAT不需要映射则在该参数中添加
	 *               CbsTargetTime.DATE_FORMAT
	 * 
	 * @param filename 
	 *           需建立Xml文件的完全路径和文件名
	 *           
	 * @return 返回操作结果, 
	 *         0表失败, 1表成功
	 */
	@SuppressWarnings("unchecked")
	public int createXMLFile(List objs, String[] unReflectProp, String filename) {
		try {
			xmlProcessor = new XMLProcessor();
			xmlProcessor.createXMLFile(objs, unReflectProp, filename);
			return 1;
		} catch (IndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			//System.out.println("传入的对象数组长度为零!");
			e.printStackTrace();
			return 0;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("生成XML异常!");
			e.printStackTrace();
			return 0;
		}
	}

}

 

package com.creawor.cbsms.client.xml.test;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.creawor.cbsms.client.model.CbsMessage;
import com.creawor.cbsms.client.model.CbsTargetTime;
import com.creawor.cbsms.client.xml.service.Object2XMLHander;
import com.creawor.cbsms.client.xml.util.XMLProcessor;

public class MyTest {

	public static void main(String[] args) {
		CbsMessage message = new CbsMessage();
		message.setChannelId(1);
		message.setData("你好 world");
		message.setBcEndType(1);
		message.setMessageNum(12);

		CbsMessage message2 = new CbsMessage();
		message2.setChannelId(2);
		message2.setData("hello world2");
		message2.setBcEndType(2);
		message2.setMessageNum(122);
		CbsTargetTime ctt = new CbsTargetTime();
		ctt.setFixedTime("fixtime");
		Calendar cal = Calendar.getInstance();
		ctt.setEndDate(new Timestamp(cal.getTimeInMillis()));
		message.setCbsTargetTime(ctt);
		String[] unReflectProp = new String[] { "CbsTargetTime.DATE_FORMAT",
				"CbsTargetTime.TIME_FORMAT", "CbsTargetTime.DATE_TIME_FORMAT",
				"CbsTargetTime.TIME_TYPE_FIXED_TIME",
				"CbsTargetTime.TIME_TYPE_TOPIC",
				"CbsTargetTime.TIME_TYPE_BC_NOW",
				"CbsTargetTime.TIME_TYPE_REAL_TIME",
				"CbsTargetTime.TIME_TYPE_CRON_EXPRESSION",
				"CbsTargetTime.TIME_TYPE_RANGE" };
		List<CbsMessage> messages = new ArrayList<CbsMessage>();
		messages.add(message);
		messages.add(message2);
		UserInfo user = new UserInfo();
		user.setPassword("password");
		user.setUsername("username");
		ctt.setUser(user);
		Object2XMLHander hander = new Object2XMLHander();
		hander.createXMLFile(messages, unReflectProp, "E:\\maosenFirst2.xml");

	}

}

 

分享到:
评论
8 楼 joachimz 2009-12-02  
yangfudong 写道
代码还是很清晰的。
自己已经实现了,为什么还要用别人的。没干的话用现成的话还可以考虑。

作为系统负责人,如果有开源好用,自己造好了轮子,我也会要求砸了用开源产品。开源产品背后是一个社区。帮你维护、测试、文档、培训人。你不可能会做得更好,而且以后招人也非常容易,不会有大的风险。
java平台发展到今天,更多应该是去整合各类成熟组件,能做好才是真正的牛!

这个还是推荐你使用xstream
7 楼 yangfudong 2009-12-02  
代码还是很清晰的。
自己已经实现了,为什么还要用别人的。没干的话用现成的话还可以考虑。
6 楼 yunzhongxia 2009-12-02  
推荐xtream
5 楼 xuyao 2008-12-03  
开头写了老大一个数组,为啥不用枚举?还有就是开源已经有很不错的了,可以参考一下。不过还是赞一下,技术没有好坏,只有好不好用
4 楼 lifethinker 2008-12-03  
xtream不错,很轻量,序列化和反序列化都相当简单。JAXB太笨重了。
3 楼 mooncui 2008-12-03  
JAXB 也可以的
2 楼 ray_linn 2008-12-03  
有个东西叫XML系列化和反系列化吧?
1 楼 kjj 2008-12-03  
xstream 不好吗,好像两行代码就可以实现这个功能吧!

相关推荐

    xml与反射.txt

    1 简述反射机制 反射是一种间接操作目标对象的机制,在程序程序...4、DOM4J解析。其中前两种属于基础方法,是 官方提供的平台无关的解析方式;后两种属于扩展方法,它们是在基础的方法上扩展出来的,只适用于java平台。

    JAVA_API1.6文档(中文)

    javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 ...

    java api最新7.0

    javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 javax....

    MyEclipse_9创建SSH2开发环境必须的独立包

    dom4j-1.6.1.jar 用来读写XML文件的 ehcache-1.5.0.jar ehcache缓存 hibernate3.jar hibernate-3.3.1.GA jar jaxen-1.1.1.jar 支持dom4j的xpath javassist-3.4.GA.jar 是一个开源的分析、编辑和创建Java字节码的类库...

    Java 1.6 API 中文 New

    javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 javax....

    JavaAPI1.6中文chm文档 part1

    javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 ...

    JavaAPI中文chm文档 part2

    javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 ...

    [Java参考文档]

    javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 ...

    [Java参考文档].JDK_API 1.6

    javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 javax....

    JavaScript王者归来part.1 总数2

     12.8.2 如何使用XML DOM--一个利用XML实现多级关联下拉选择框的例子   12.9 总结   第13章 事件处理  13.1 什么是事件   13.1.1 消息与事件响应   13.1.2 浏览器的事件驱动机制   13.2 基本事件处理  ...

    JDK_1_6 API

    javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 javax...

    Visual.Basic.2010.&.NET4.高级编程(第6版)-文字版.pdf

    9.5.2 system.xml.xsl中定义的其他类和接口 370 9.6 asp.net中的xml 370 9.6.1 xmldatasource服务器控件 370 9.6.2 xmldatasource控件的名称空间问题 374 9.6.3 xml服务器控件 375 9.7 linq to xml 376 ...

    【卷一/共两卷】AJAX实战pdf高清版90M

    2.5.2 XMLDocument和XMLHttpRequest对象 2 5.3 向服务器发送请求 2.5.4 使用回调函数监视请求 2.5.5 完整的生命周期 2.6 Ajax有何不同 2.7 小结 2.8 资源 第3章 使AjaX秩序井然 3.1 从混沌到秩序 3.1.1 模式:创造...

    亮剑.NET深入体验与实战精要2

    6.3.7 项目案例:通用自定义XML配置类 263 6.4 ADO.NET与XML 266 6.4.1 读XML文档到DataSet 266 6.4.2 DataSet转为XML文档 267 6.5 项目案例1:实现网站的RSS应用 267 6.6 项目案例2:在线实现RSS阅读器 270 本章...

    亮剑.NET深入体验与实战精要3

    6.3.7 项目案例:通用自定义XML配置类 263 6.4 ADO.NET与XML 266 6.4.1 读XML文档到DataSet 266 6.4.2 DataSet转为XML文档 267 6.5 项目案例1:实现网站的RSS应用 267 6.6 项目案例2:在线实现RSS阅读器 270 本章...

    JAVA面试题最全集

    IS09000和CMM(软件能力成熟度模型)认证是国际上通用的软件质量评估方法.CMM的五个成熟度等级。 第一,谈谈final, finally, finalize的区别。 final?修饰符(关键字)如果一个类被声明为final,意味着它不能再...

Global site tag (gtag.js) - Google Analytics