`
easion_zms
  • 浏览: 96256 次
  • 性别: 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 不好吗,好像两行代码就可以实现这个功能吧!

相关推荐

    dom4j+反射,面向对象方式的xml格式转换

    我们可以创建一个User类,包含id、name和age字段,然后用DOM4J解析XML,通过反射创建User对象并设置属性。这个过程可以封装成一个通用的方法,以适应不同结构的XML数据转换。 总之,DOM4J提供了强大且易用的工具来...

    基于j'ava的dom4j包

    在DOM4J中,可能用到ASM来处理Java反射和动态代理,尤其是在运行时对XML处理的类进行动态生成或修改时。 DOM4J的使用方法包括: - **解析XML**:使用`DocumentBuilderFactory`创建`DocumentBuilder`,然后通过`...

    java 根据javaBean反射自定义导出 excel、xml、pdf、csv

    2. **XML**:可以使用JAXB(Java Architecture for XML Binding)或者DOM、SAX、StAX等API来生成XML文件。首先,为JavaBean创建一个对应的XML Schema(XSD),然后使用JAXB将JavaBean对象转换成XML文档。 3. **PDF*...

    提供dom4j的源代码

    作为开源项目,DOM4J的源代码对于理解XML解析、操作和生成的过程具有很高的学习价值。源代码以.java文件的形式存在,这使得开发者可以直接查看和研究其内部实现。 **1. DOM4J基本概念** DOM4J的主要目标是提供一个...

    xml与反射.txt

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

    excel和xml解析需要引入的jar包

    本主题涉及的jar包是为了解析和操作Excel(主要基于Apache POI)和XML(可能包括DOM4J和XMLBeans)文件。下面我们将详细探讨这些库及其在Excel和XML处理中的作用。 1. Apache POI: - **poi-3.11-20141221.jar**: ...

    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通用范例开发金典源代码

    《Java通用范例开发金典源代码》是一个包含大量Java编程示例的资源集合,旨在帮助开发者深入理解和掌握Java编程语言的各种特性和应用场景。这个压缩包文件中的源代码覆盖了Java语言的基础到高级各个方面,是Java学习...

    spring(1)

    DOM4J是一个Java库,用于处理XML、XSLT和XPath,它使得解析XML文件变得简单。DTD则是一种规范,用于定义XML文档的结构,确保文档的合法性。Spring框架使用DOM4J解析配置文件,并依据DTD验证XML的结构是否正确。 综...

    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 元素和结构的类。 ...

    [Java参考文档]

    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参考文档].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 基本事件处理  ...

Global site tag (gtag.js) - Google Analytics