`

自己实现的XML和Entity映射工具XmlHandler

阅读更多

公司不允许随便下载第三方jar包,但是公司lib库中的jar又非常老,更新需要申请,很多时候都是自己去写一些工具类,这次遇到xml处理的一些程序,于是自己写了一个工具类。这个比较粗糙,属于Test版本。

实体类注解@XmlEntity:

package com.cugxw.utils;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author cugxw
 * @date 2012-10-11
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface XmlEntity {
	/**
	 * Map namespace name of the XML.<br>
	 * If this value is "$Default$", the namespace name will be class namespace name.<br>
	 * If class namespace is unnamed, the XML namespace will be null. <br>
	 */
	String namespace() default "$Default$";
	
	/**
	 * Map root name of the XML.<br>
	 * If this value is "$Default$", the XML root name will be simple class name.<br>
	 */
	String name() default "$Default$";
	
	/**
	 * Map prefix of the elements.<br>
	 * If this value is "$Default$", all elements of the XML will have no prefix string.<br>
	 */
	String xmlPrefix() default "$Default$";
}

 实体类field注解@XmlField

package com.cugxw.utils;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author cugxw
 * @date 2012-10-11
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface XmlField {
	/**
	 * Map the element name of the XML.
	 * If this value is "$Default$", the elements' name of the XML will be class field name.
	 */
	String name() default "$Default$";
}

 Xml处理类,包含toXML和fromXML方法:

package com.cugxw.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;

@SuppressWarnings("unchecked")
public class XmlHandler {
	
	//Registed entity name 
	private  Map regClassMap;
	
	//Entity path, default src root directory.
	private boolean useXmlAnnotation = false;
	
	public XmlHandler()
	{
		this.regClassMap = new HashMap();
		this.registClass(null);
	}
	
	public XmlHandler(String entityPath)
	{
		this.regClassMap = new HashMap();
		this.registClass(entityPath);
	}
	
	public XmlHandler(String entityPath, boolean useXmlAnnotation)
	{
		this.regClassMap = new HashMap();
		this.useXmlAnnotation = useXmlAnnotation;
		this.registClass(entityPath);
	}
	
	/**
	 * Get all loaded classes, return them.
	 * @return
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	private List getLoadedClass() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
		ClassLoader curClassLoader = Thread.currentThread().getContextClassLoader();
		Class loaderClass = curClassLoader.getClass();
		
		/* Find all loaded classes in classloader */
		while (!loaderClass.equals(ClassLoader.class)) {
			loaderClass = loaderClass.getSuperclass();
		}
		
		/* Get the access to read private field */
		Field loaderField = loaderClass.getDeclaredField("classes");
		loaderField.setAccessible(true);
		
		return (List) loaderField.get(curClassLoader);
	}
	
	private String getXmlEntityName(Class<Object> clazz) {
		Object obj = clazz.getAnnotation(XmlEntity.class);
		if (obj == null) {
			return null;
		}
		return clazz.getAnnotation(XmlEntity.class).name();
	}
	
	public void registClassName(Class clazz) {
		String className = clazz.getName();
		if (this.useXmlAnnotation) {
			String xmlEntityName = getXmlEntityName(clazz);
			if (xmlEntityName != null && !"".equals(xmlEntityName)) {
				this.regClassMap.put(clazz.getSimpleName(), 
						className);
				System.out.println(className);
			}
		} else {
			this.regClassMap.put(clazz.getSimpleName(), 
					className);
			System.out.println(className);
		}
	}
	
	/**
	 * Regist all loaded classes, put them into a map.
	 * @param regPath
	 */
	public void registClass(String regPath) {
		try {
			List classList = this.getLoadedClass();
			int count = classList.size();
			for(int i=0; i<count; i++) {
				Object clazz = classList.get(i);
				String className = ((Class)clazz).getName();
				if (regPath == null || "".equals(regPath)) {
					this.registClassName((Class)clazz);
				} else {
					if (className.startsWith(regPath)) {
						this.registClassName((Class)clazz);
					}
				}
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Get field value from one object by field name 
	 * @param fieldName
	 * @param obj
	 * @return field value of the object;
	 */
	private Object getFieldValueByName(String fieldName, Object obj) throws Exception 
	{    
		String firstLetter = fieldName.substring(0, 1).toUpperCase();    
		String getter = "get" + firstLetter + fieldName.substring(1);    
		Method method = obj.getClass().getMethod(getter, new Class[] {});    
		Object value = method.invoke(obj, new Object[] {});
		return value;
	}  
	
	/**
	 * A sub task of addition sub element by calling recursion method
	 * @param pElement
	 * @param subElementName
	 * @param prefix
	 * @param textValue
	 * @return sub element
	 */
	private  Element addSubElement(Element pElement, String subElementName, 
			String prefix, String textValue)
	{
		QName qname = QName.get(subElementName);
		if(prefix != null && !"".equals(prefix))
		{
			qname = QName.get(prefix + ":" + subElementName);
		}
		Element node = pElement.addElement(qname);
		if(textValue != null && !"".equals(textValue))
		{
			node.setText(this.nullToStr(textValue));
		}
		return node;
	}
	
	private String getXmlFieldName(Field field) {
		String xmlFieldName = null;
		if (this.useXmlAnnotation) {
			XmlField xmlField = field.getAnnotation(XmlField.class);
			if (xmlField != null) {
				if (!"$Default$".equals(xmlField.name())) {
					xmlFieldName = xmlField.name();
					return xmlFieldName;
				}
			}
		}
		xmlFieldName = field.getName();
		return xmlFieldName;
	}
	
	/**
	 * A sub task of create sub xml by Recursion method
	 * @param element
	 * @param prefix
	 * @param obj
	 */
	private void createSubXml(Element element, String prefix, Object obj) throws Exception
	{
		if(obj == null)
		{
			return;
		}
		Class objClass = obj.getClass();
		Field[] fields = objClass.getDeclaredFields();
		for(int i=0; i<fields.length; i++)
		{
			String fieldName = fields[i].getName();
			String xmlFieldName = getXmlFieldName(fields[i]);
			Object fieldVal = this.getFieldValueByName(fieldName, obj);
			String fieldClassName = fields[i].getType().getSimpleName();
			if(fieldClassName == null || "".equals(fieldClassName)
					|| this.regClassMap == null)
			{
				continue;
			}
			
			String classFullName = (String) this.regClassMap.get(fieldClassName);
			if(classFullName != null && !"".equals(classFullName))
			{
				Element subElement = this.addSubElement(element, xmlFieldName, prefix, null);
				this.createSubXml(subElement, prefix, fieldVal);
			}
			else if(fieldVal != null && ("List".equals(fieldClassName) || "ArrayList".equals(fieldClassName)))
			{
				/* When sub class in a list object */
				Element subElement = this.addSubElement(element, xmlFieldName, prefix, null);
				Collection collection = (Collection) fieldVal;
				for(Object aVal : collection)
				{
					Element grandSubEle = this.addSubElement(subElement, aVal.getClass().getSimpleName(), prefix, null);
					this.createSubXml(grandSubEle, prefix, aVal);
				}
			}
			else if(fieldVal != null && ("Set".equals(fieldClassName) || "HashSet".equals(fieldClassName)))
			{
				/* When sub class in a set object */
				Element subElement = this.addSubElement(element, xmlFieldName, prefix, null);
				Set set = (Set)fieldVal;
				Iterator it = set.iterator();
				while(it.hasNext())
				{
					Object aVal = it.next();
					Element grandSubEle = this.addSubElement(subElement, aVal.getClass().getSimpleName(), prefix, null);
					this.createSubXml(grandSubEle, prefix, aVal);
				}
			}
			else if(fieldVal != null)
			{
				this.addSubElement(element, xmlFieldName, prefix, this.nullToStr(fieldVal));
			}
		}
	}
	
	/**
	 * Get QName by entity object
	 * @param obj entity object
	 * @return QName
	 */
	private QName getQName(Object obj) {
		QName qname = null;
		String namespace = null;
		String prefix = null;
		if (this.useXmlAnnotation) {
			XmlEntity xmlEntity = obj.getClass().getAnnotation(XmlEntity.class);
			if (xmlEntity != null) {
				String elementName = obj.getClass().getSimpleName();
				if (!"$Default$".equals(xmlEntity.name())) {
					elementName = xmlEntity.name();
				}
				if (!"$Default$".equals(xmlEntity.namespace())) {
					namespace = xmlEntity.namespace();
				}
				if (!"$Default$".equals(xmlEntity.xmlPrefix())) {
					prefix = xmlEntity.xmlPrefix();
				}
				qname = QName.get(elementName, prefix, namespace);
				return qname;
			}
		}
		QName.get(obj.getClass().getSimpleName());
		return qname;
	}
	
	/**
	 * Get xml data from an entity
	 * @param obj
	 * @param namespace
	 * @param prefix
	 * @return string data
	 */
	public String toXml(Object obj) throws Exception
	{
		if(obj != null)
		{
			QName qname = this.getQName(obj);
			Element root = DocumentHelper.createElement(qname);
			
			String prefix = qname.getNamespacePrefix();
			if ("".equals(prefix)) {
				prefix = null;
			}
			
			this.createSubXml(root, prefix, obj);
		
			Document document = DocumentHelper.createDocument(root);
			return document.asXML();
		}
		return null;
	}
	
	/**
	 * A sub work of parse sub xml via Recursion method
	 * @param obj
	 * @param element
	 */
	private void parseSubXml(Object obj, Element element)
	{
		/* The object and element must not be null */
		if(obj == null || element == null)
		{
			return;
		}
		
		/* Get the all declared fields */
		Field[] fields = obj.getClass().getDeclaredFields();
		
		if(fields != null)
		{
			for(int i=0; i<fields.length; i++)
			{
				/* Get the field information */
				Field aField = fields[i];
				Class fieldClass = aField.getType();
				String fieldClassName = fieldClass.getSimpleName();
				String xmlFieldName = this.getXmlFieldName(aField);
				
				if(this.regClassMap == null)
				{
					continue;
				}
				
				/* Get class name from registed class map if the class is registered */
				String classFullName = (String) this.regClassMap.get(fieldClass.getSimpleName());
				Element subEle = element.element(xmlFieldName);
				
				// Make the field be accessible
				fields[i].setAccessible(true);
				
				Object value = null;
				
				if(classFullName != null && !"".equals(classFullName))
				{
					/* Create an object of this sub class if it's a class which is registered */
					try {
						value = fieldClass.newInstance();
					} catch (InstantiationException e) {
						e.printStackTrace();
						return;
					} catch (IllegalAccessException e) {
						e.printStackTrace();
						return;
					}
					
					this.parseSubXml(value, subEle);
					
				}
				else if(subEle != null && ("List".equals(fieldClassName) || "ArrayList".equals(fieldClassName)))
				{
					/* When sub class in a list object */
					List objList = new ArrayList();
					List<Element> eleList = subEle.elements();
					for(Element aEle : eleList)
					{
						if(aEle != null)
						{
							String fullPath = (String) this.regClassMap.get(aEle.getName());
							Object aVal = null;
							try {
								aVal = Class.forName(fullPath).newInstance();
							} catch (InstantiationException e) {
								e.printStackTrace();
								return;
							} catch (IllegalAccessException e) {
								e.printStackTrace();
								return;
							} catch (ClassNotFoundException e) {
								e.printStackTrace();
								return;
							}
							this.parseSubXml(aVal, aEle);
							objList.add(aVal);
						}
					}
					value = objList;
				}
				else if(subEle != null && ("Set".equals(fieldClassName) || "HashSet".equals(fieldClassName)))
				{
					/* When sub class in a set object */
					Set objSet = new HashSet();
					List<Element> eleList = subEle.elements();
					for(Element aEle : eleList)
					{
						if(aEle != null)
						{
							String fullPath = (String) this.regClassMap.get(aEle.getName());
							Object aVal = null;
							try {
								aVal = Class.forName(fullPath).newInstance();
							} catch (InstantiationException e) {
								e.printStackTrace();
								return;
							} catch (IllegalAccessException e) {
								e.printStackTrace();
								return;
							} catch (ClassNotFoundException e) {
								e.printStackTrace();
								return;
							}
							this.parseSubXml(aVal, aEle);
							objSet.add(aVal);
						}
					}
					value = objSet;
				}
				else if(subEle != null)
				{
					// Get the common value if it's not a class which is registered
					value = subEle.getText();
				}
				
				/*set the fields' value*/
				if(value != null && !"".equals(value))
				{
					try {
						fields[i].set(obj, value);
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
						return;
					} catch (IllegalAccessException e) {
						e.printStackTrace();
						return;
					}
				}
			}
		}
	}
	
	/**
	 * Get a entity object from xml
	 * @param entityClass
	 * @param xml
	 * @return a entity object
	 * @throws DocumentException 
	 */
	public Object fromXml(Class entityClass, String xml) throws Exception
	{
		/* Create a new object of the entity */
		Object resObj = null;
		
		/* Get the root of the xml */
		Document document = null;
		Element root = null;
		document = DocumentHelper.parseText(xml);
		root = document.getRootElement();
		
		if(entityClass != null)
		{
			String xmlEntityName = this.getXmlEntityName(entityClass);
			if(!xmlEntityName.equals(root.getName()))
			{
				return null;
			}
			
			/* Parse the XML */
			resObj = entityClass.newInstance();
			this.parseSubXml(resObj, root);
		}

		return resObj;
	}
	
	/**
	 * May be,we need to converse null to blank String
	 * @param obj
	 * @return string
	 */
	private String nullToStr(Object obj)
	{
		if(obj == null)
		{
			return "";
		}
		return obj.toString();
	}
	
	public boolean isUseXmlAnnotation() {
		return useXmlAnnotation;
	}

	public void setUseXmlAnnotation(boolean useXmlAnnotation) {
		this.useXmlAnnotation = useXmlAnnotation;
	}
	
	public void showRegMap() {
		Set mSet = this.regClassMap.keySet();
		for (Object clazzName : mSet) {
			System.out.println(clazzName);
		}
	}
}

 

分享到:
评论

相关推荐

    mybatis自动生成Mapper.xml,entity,dao

    "mybatis自动生成Mapper.xml,entity,dao"是MyBatis的一个实用功能,可以帮助开发者自动根据数据库表结构生成对应的Java实体类(Entity)、XML映射文件(Mapper.xml)和数据访问对象(DAO)类,极大地提高了开发效率...

    XXE全称XML External Entity Injection漏洞.pdf

    XXE全称XML External Entity Injection漏洞,是一种在应用程序解析XML输入时由于未能禁止外部实体加载而引发的安全漏洞。该漏洞可以被利用来执行文件读取、命令执行、内网端口扫描等多种攻击。 XML(eXtensible ...

    c# XML 与实体相互转换 源代码

    在压缩包中的`xmlEntity`文件可能是实现这些转换的源代码,包括实体类定义和转换方法的具体实现。分析并理解这些代码可以帮助我们更深入地了解作者是如何处理XML和实体对象的转换的。 总的来说,XML与实体对象的...

    生成entity和mybatis映射文件

    在IT行业中,MyBatis是一...总的来说,"生成entity和mybatis映射文件"的资源对于基于MyBatis的Java项目来说是一大利器,它提升了开发效率,降低了出错概率,使得开发团队能够更专注于业务的实现,而非基础架构的搭建。

    利用hibernate自动生成hbm.xml文件和entity类.doc

    Hibernate 反向工程是指使用 Hibernate 工具将数据库表结构反向生成对应的 Entity 类和 hbm.xml 文件的过程。这种方法可以大大简化开发过程,提高开发效率。 二、 Hibernate 反向工程的步骤 1. 切换到 MyEclipse ...

    String.xml Excel 相互转换工具

    从提供的文件列表来看,`Test.java`可能是用于测试工具功能的代码,`ExcelHandle.java`可能是处理Excel读写的核心类,而`entity`可能包含了一些数据结构定义,比如表示`String.xml`文件元素或Excel表格行的类。...

    xml与实体类转换工具

    本文将详细介绍如何使用工具类进行XML与实体类的转换,并探讨相关依赖和实现方法。 首先,XML转换为Java实体类的基本原理是通过解析XML文档,创建对应的Java对象。Java中常用的库有JAXB(Java Architecture for XML...

    .NET2.0映射工具

    .NET 2.0 映射工具是用于简化数据库与应用程序之间数据交互的开发工具,它自动为数据库中的表创建对应的类,从而免去了开发者手动编写这些类的繁琐工作。这种映射技术通常被称为对象关系映射(ORM,Object-...

    Hibernate逆向生成entity和hbm.xml文件

    在开发过程中,为了减少手动编写实体类(Entity)和对应的hbm.xml配置文件的工作量,Hibernate提供了一个逆向工程工具,可以基于现有数据库结构自动生成这些代码。 实体类是Java对象,它们代表数据库中的表,而hbm....

    自动生成entity mapper工具包

    总之,自动生成`entity`和`mapper`的工具包是MyBatis开发中的利器,它简化了代码生成过程,降低了开发成本,使得开发者能更专注于业务逻辑的实现。通过熟练掌握MyBatis Generator的使用,能够有效提升开发效率和代码...

    逆向工程生成entity,mapper,mapper.xml

    在这个特定的场景中,"逆向工程生成entity,mapper,mapper.xml"指的是利用逆向工程工具来自动生成Java编程中的实体类(Entity)、映射器接口(Mapper)以及对应的XML配置文件。这些组件在Java企业级应用,特别是基于...

    根据mysql自动生成entity、mapper、xml

    而“根据mysql自动生成entity、mapper、xml”这个话题涉及到的是使用特定工具或插件来自动化生成MyBatis框架所需的实体类(Entity)、Mapper接口以及对应的XML配置文件,这样可以极大地提高开发效率,减少手动编写...

    XML轻松学习手册 / XML技术 /

    XML和HTML的区别 · 六. XML的严格格式 · 七. 关于XML的更多 · 第二章:XML概念 · 一. 扩展性 · 二. 标识 · 三. 语言 · 四. 结构化 · 五. Meta数据 · 六. 显示 · 七. DOM · 第三章:XML的术语 ·...

    自动生成Mybatis 实体类、DaoMapper、XML可视化界面工具

    总之,这个工具为Mybatis开发提供了极大的便利,通过可视化的界面,开发者可以快速生成和管理实体类、Mapper接口以及XML映射文件,极大地提高了开发效率,减少了错误的可能性,同时也降低了学习和使用Mybatis的门槛...

    xml映射实体对象

    自己写的一个xml映射实体对象类,附件为一个AXIS客户端代码生成文档

    自动生成entity和dao层

    在传统的手动编码方式中,开发者需要为每个表编写对应的DAO接口和实现,这是一项重复且耗时的工作。 为了自动化这个过程,我们可以利用代码生成工具。在给定的“自动生成entity和dao层”的场景中,可能是使用了类似...

    Spring Boot Mybatis 自动生成Entity,controller、serviceImpl ,Dao,方便开发,无需手写

    Mybatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 3. **自动生成代码**: 自动代码生成是这个项目的核心功能,它可以帮助...

    springboot+mybatis逆向生成controller+service+mapper+entity

    MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 逆向工程(Reverse Engineering)在这里指的是从现有的数据库结构自动...

    Devart Entity Developer v6.4.719 Professional破解版,支持vs2019

    强大的代码生成 Entity Developer提供基于T4类似的模板生成代码框架,针对不同使用情况提供大量预定义的模板,模板化生成上下文,实体,映射,支持流,属性和XML映射,包括持久层感知和持久层无感知实体,支持验证...

    操作XML方法大全

    - 从XML还原对象:反之,将XML数据映射回对象实例,实现数据持久化。 4. **XPath查询**: - XPath语言用于查找XML文档中的节点,可以根据路径、属性、节点名等多种条件进行定位。 - XPath表达式可以用来选取节点...

Global site tag (gtag.js) - Google Analytics