一、前言

国庆假期临近,工作动力不强。所以写几篇之前项目中自己用到的一些可能有用的东西分享出来。

今天分享的是Xml与javaBean互转的自定义实现。

先说几种我知道的Xml与javaBean互转的方式:

1、可以利用StringBuilder执行拼接,这样比较费时且复用性低

2、利用JAXB、jackson等一些公开API调用进行转换,这样最方便最简单

3、利用Dom4j实现

这三种一般来说肯定优先选第二种。

但是出于学习的目的。我在之前的项目中自己利用Dom4j完成xml与javaBean的互转。

由于使用场景还不多,代码健壮性目前有待完善。后续使用在更多场景下会一步一步优化完善,如果有朋友有一些优化建议

欢迎在评论区指出。

**二、公共类 ReflectDTO **

这个接口这里主要作用是一个标识作用.

如果需要控制类中某些属性无需转换。可以加一些注解之类的来控制,由于我没有这种需求所以没有实现这功能。

需要转换的对象来实现这个接口,在处理过程中会将实现该接口的类信息转换

import java.io.Serializable;

/**
* @author hhb
* @date :2021/8/20 14:23
*/
public interface ReflectDTO extends Serializable {
}

三、Xml转JavaBean

3.1、方法入口。首先 利用Dom4j 将String格式的xml转化成Document类型的对象,然后通过递归、反射实现转化

    /**
* 将Xml格式的字符串转换为java对象
* @param xml
* @param cls
* @return
* @throws DocumentException
* @throws IllegalAccessException
*/
public static <T> T parseXml(String xml,Class<T> cls) throws DocumentException,IllegalAccessException {
//xml格式字符串转Dom4j的Document
Document document = DocumentHelper.parseText(xml);
//递归处理子元素
return (T)handleElement(document.getRootElement(), cls,null,null);
}

3.2、递归方法。递归处理Document元素,将element里面的text匹配上对象的属性并赋值

    /**
* 递归处理元素
* @param root
* @param rootClz
* @param rootObj
* @param rootField
* @return
* @throws IllegalAccessException
*/
private static Object handleElement(Element root, Class rootClz, Object rootObj,Field rootField) throws IllegalAccessException {
//创建对象公共方法
Object fieldObj = creatObj(rootClz);
List<Element> elements = root.elements();
//获取带转换类已声明的属性
Field[] fields = rootClz.getDeclaredFields();
for (Element e:elements){
//细节处理,后续可进一步完善属性可能的类型
handleDetail(fields,e,fieldObj);
}
if (null!=rootObj&&null!=rootField){
rootField.set(rootObj,fieldObj);
}
return fieldObj;
}

3.3、 基础方法。根据对象的class信息生成新的对象,还有根据Element的名称匹配对象中

对应的相应属性信息。


/**
* 根据类信息生成对象
* @param cls
* @return
*/
private static Object creatObj(Class cls){
try {
return cls.getConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
} /**
* Documet元素标签匹配对象属性
* @param fields
* @param name
* @return
*/
private static Field matchFields(Field[] fields, String name) {
for (Field field: fields){
if (field.getName().equals(name)){
return field;
}
}
return null;
}

3.4、 处理核心方法。主要是根据对象属性的类型采取对应的处理方式目前已实现的有,

实现了ReflectDTO接口的对象、String、List。后面如果还有其他类型可以

自己按照已有示例进行扩展


/**
* 处理核心
* @param fields
* @param e
* @param fieldObj
* @throws IllegalAccessException
*/
private static void handleDetail(Field[] fields,Element e,Object fieldObj) throws IllegalAccessException {
//匹配属性,没匹配上直接返回
Field field=matchFields(fields,e.getName());
if (null==field){
return;
}
field.setAccessible(true);
Class<?> fieldType = field.getType();
//如果是List
if (fieldType.equals(List.class)&&field.getGenericType() instanceof ParameterizedType){
List list = handleListDetail(e, field);
field.set(fieldObj,list);
return;
}
//获得属性值
Object childFieldValue = creatObj(fieldType);
//如果是String
if (fieldType.equals(String.class)){
field.set(fieldObj,e.getText());
}
//todo 这里还可以扩展,比如BigDecimal、LocalDateTime、Double等等
//需要转换的对象
if (childFieldValue instanceof ReflectDTO){
Object o=handleElement(e,fieldType,fieldObj,field);
field.set(fieldObj,o);
}
}

3.5、处理特殊方法。如果待生成属性是list时的一些处理方法,主要有获取List里面的对象的实际类型方法,

处理List属性时的明细方法。

    /**
* 列表类型处理明细
* @param listElement
* @param field
* @return
* @throws IllegalAccessException
*/
private static List handleListDetail(Element listElement,Field field) throws IllegalAccessException {
ArrayList objList = new ArrayList<>();
Class<?> classInList = getClassInList(field.getGenericType());
for (Element e: listElement.elements()){
Object objInList = handleElement(e, classInList, null, null);
objList.add(objInList);
}
return objList;
} /**
* 获得List里面的对象类型
* @param fieldType
* @return
*/
private static Class<?> getClassInList(Type fieldType){
ParameterizedType paramType = (ParameterizedType) fieldType;
Type[] genericTypes = paramType.getActualTypeArguments();
if (genericTypes != null && genericTypes.length > 0) {
if (genericTypes[0] instanceof Class<?>) {
return (Class<?>) genericTypes[0];
}
}
return null;
}

四、 javaBean转Xml的实现

由于该篇篇幅较长,这个实现将放在下一篇进行说明.

最新文章

  1. BPM配置故事之案例11-操作外部数据源
  2. 如何优化cocos2d程序的内存使用和程序大小
  3. oracle 空间大小查询
  4. PHP 对于 MYSQL 基础操作
  5. DAY1 linux 50条命令
  6. ducument.ready不生效的问题 ruby on rails
  7. Mongodb数据库加密存储(python)
  8. 获取唯一UUID/UDID方案
  9. 解决:操作无法完成(错误0x00000709)。再次检查打印机名称,并确保打印机已连接到.
  10. socket的NIO操作
  11. 关于linux开机自启
  12. Model Thinking1
  13. Scala - 快速学习01 - Scala简介
  14. MS-DOS 系统汇编环境之DOSBOX+vim
  15. MySQL中innodb_flush_log_at_trx_commit的设置
  16. Angular 4 路由时传递数据
  17. uva--242(邮资问题 dp)
  18. thinkphp3.2.3+smarty解决success调用模板错误心得
  19. 微信小程序 跳坑
  20. Tomcat 监控的几种方法

热门文章

  1. 【java虚拟机】常用的jvm配置参数
  2. BootStrap Table超好用的表格组件基础入门
  3. 寻找最短路径Dijkstra算法
  4. rabbitMq可靠性投递之手动ACK
  5. 修改anaconda3 jupyter notebook 默认路径
  6. JavaWeb中表单数据的获取及乱码问题
  7. Python 高级特性(1)- 切片
  8. WPF 过渡效果
  9. Python脚本运行出现语法错误:IndentationError:unexpected indent
  10. UVA 1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)