基于dom4j的xml映射实体的工具类(java)
工具是基于dom4j,使用反射使实体属性与xml的标签关联,目前兼容List,Map后续更新兼容。
历史更新:
发布-2019-6-22
增加注解@XmlAttr关联实体与xml(解决实体名与xml属性名不相同的情况)-2019-7-12
背景故事:这是个大哥与小弟的团队关系
xml文件
大哥
70
小弟1
50
小小弟1-1
45
小小弟1-2
45
小弟2
51
小小弟2-1
50
小小弟2-2
50
实体
1)大哥的实体
import java.util.List;
public class BigBro {
@XmlAttr("name")
private String name;
@XmlAttr("power")
private String power;
@XmlAttr("brolist")
private List brolist;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPower() {
return power;
}
public void setPower(String power) {
this.power = power;
}
public List getBrolist() {
return brolist;
}
public void setBrolist(List brolist) {
this.brolist = brolist;
}
}
2)小弟的实体
import java.util.List;
public class Bro {
@XmlAttr("name")
private String name;
@XmlAttr("power")
private String power;
@XmlAttr("")
private List littlebrolist;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPower() {
return power;
}
public void setPower(String power) {
this.power = power;
}
public List getLittlebrolist() {
return littlebrolist;
}
public void setLittlebrolist(List littlebrolist) {
this.littlebrolist = littlebrolist;
}
}
XmlReader代码
import Annotation.XmlAttr;
import Annotation.XmlAttrImplicit;
import entity.RspPerson;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.StringReader;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class XmlReader {
public XmlReader() {
}
/**
* 映射xml到实体
* @param clazz
* @param xmlStr
* @param
* @return
*/
public T parseToEntity(Class clazz, String xmlStr) {
SAXReader reader = new SAXReader();
reader.setEncoding("GBK");
Document doc;
T obj = null;
try {
obj = clazz.getDeclaredConstructor().newInstance();
doc = reader.read(new StringReader(xmlStr));
Element root = doc.getRootElement();
handleNode(root, obj);
} catch (DocumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return obj;
}
/**
* 处理节点
* @param element
* @param t
* @param
*/
public void handleNode(Element element, T t) {
for (Iterator it = element.elementIterator(); it.hasNext();) {
Element child = it.next();
Field field = null;
try {
field = getFieldByAttrName(child.getName(), t);
if (field == null) {
return ;
}
PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), t.getClass());
Class> clazz = Class.forName(field.getType().getTypeName());
Object childObject = null;
if (descriptor.getPropertyType().getTypeName().equals("java.util.List")) {
childObject = Proxy.newProxyInstance(RspPerson.class.getClassLoader(), new Class[] {clazz}, new MyHandler());
} else {
childObject = Class.forName(field.getType().getTypeName()).getDeclaredConstructor().newInstance();
}
Method setMethod = descriptor.getWriteMethod(); //获得set方法
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
//带参数类型的属性
ParameterizedType pt = (ParameterizedType)type; //获取参数类型
// System.out.println("带参数" + type.getTypeName());
String paramClassName = pt.getActualTypeArguments()[0].getTypeName(); //获取实体属性的参数类型,如List的A
if (childObject instanceof List) {
ArrayList childList = new ArrayList();
Iterator childIterator = child.elementIterator();
while (childIterator.hasNext()) {
Element sonOfElement = childIterator.next();
System.out.println(sonOfElement.getName());
Object paramObject = Class.forName(paramClassName).getDeclaredConstructor().newInstance();
childList.add(paramObject);
handleNode(sonOfElement, paramObject);
}
setMethod.invoke(t, childList);
} else if (childObject instanceof HashMap){
//HashMap类型属性...
}
} else {
//不带参数类型的属性
// System.out.println("非带参数" + type.getTypeName());
setMethod.invoke(t, child.getData());
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IntrospectionException e) {
e.printStackTrace();
}
}
}
private Field getFieldByAttrName(String xmlAttrName, T t) {
for (Field f : t.getClass().getDeclaredFields()) {
if (f.isAnnotationPresent(XmlAttr.class)) {
if(f.getAnnotation(XmlAttr.class).value().equals(xmlAttrName)){
return f;
}
} else if (f.isAnnotationPresent(XmlAttrImplicit.class)) {
if (f.getAnnotation(XmlAttrImplicit.class).value().equals(xmlAttrName)){
return f;
}
}
}
return null;
}
}
-MyHandler代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
class MyHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
}
-@XmlAttr 注解
package Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 普通属性,基本数据类型的包装类
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface XmlAttr {
String value() default "";
}
-@XmlAttrImplicit注解
package Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 属性为集合接口List,Map等类型
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface XmlAttrImplicit {
String value() default "";
}
结果