·在上周留下了一个关于XMLUtil的问题,问题大概是这样的,需要通过读取一个XML文件,然后在内存中生成一个对应的javaBean。之前写的那个很是糟糕,照着一个XML去写了一个"Util",拓展性,可维护性几乎为0,所有的东西全都写死,完全就写了一个"不伦不类"的"Util",很是郁闷,点击查看之前的代码,所以痛定思痛,打算在本周对上次的Util进行重写,一直拖到今天才花了几个小时写好,不得不感叹我的拖延至之严重!

·下面贴出代码,先是两个实体类

Student(学生类)

package com.taoyuan.entity.custom;/*** @ClassName: Student* @Description: TODO Student实体类设计* @author: Han* @date: 2016-3-31 下午4:54:04*/
public class Student {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "this student`s id is " + this.id + " and name is " + this.name;}
}

Class(班级类)可以明显看到两个类是关联关系,在Class类中含有一个Student的集合

package com.taoyuan.entity.custom;import java.util.List;/*** @ClassName: Class* @Description: TODO Class班级实体类设计* @author: Han* @date: 2016-3-31 下午4:58:21*/
public class Class {private int id;private String className;private List<Student> student;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public List<Student> getStudents() {return student;}public void setStudents(List<Student> student) {this.student = student;}@Overridepublic String toString() {return "This class`s id is " + this.id + " and name is " + this.className+ "\t\nit`s students are " + this.student;}
}

XML文件

<?xml version="1.0" encoding="UTF-8"?>
<Entity><Class classPath="com.taoyuan.entity.custom.Class"><Int name="id">1</Int><String name="className">软件工程</String><Student name="student" type="list"><!-- Student数组 --><Student classPath="com.taoyuan.entity.custom.Student"><Int name="id">1</Int><String name="name">李明</String></Student><Student  classPath="com.taoyuan.entity.custom.Student"><Int name="id">2</Int><String name="name">狗蛋</String></Student></Student></Class>
</Entity>

XMLUtil利用反射,递归等实现的Util,较之前有了很大的改动,再也不用对着一个Util狂改,把通用性将到了0...现在只需要修改XML和Java实体类就可以了

package com.taoyuan.utils;import java.io.File;
import java.io.FileNotFoundException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;/*** @ClassName: XMLUtil* @Description: TODO XML工具类* @author: Han* @date: 2016-3-22 下午3:09:03*/
public class XMLUtil {/*** @Title: toEntity* @Description: TODO 将XML文件转换为一个entity* @param xmlPath* @return* @throws Exception* @return: Object*/public static Object toEntity(String xmlPath) throws Exception{//初始化,将XML文件读入内存,生成DocumentDocument _document = init(xmlPath);//获取根目录节点Element _rootEle = _document.getRootElement();String _rootName = "";if(_rootEle != null){//根目录节点名字_rootName = _rootEle.getName();}if(!_rootName.equals("Entity")){throw new Exception("请确认根节点名字是否为Entity");}List<Element> elements = _rootEle.elements();//在Entity节点中无子节点if(elements.size() == 0){return null;}return getEntity(elements.get(0));}/*** 获取根据节点Element获取对应的Entity* @param element* @return* @throws ClassNotFoundException* @throws InstantiationException* @throws IllegalAccessException*/@SuppressWarnings("rawtypes")private static Object getEntity(Element element)throws ClassNotFoundException, InstantiationException,IllegalAccessException {//获取classPathString _classPath = element.attributeValue("classPath");//获取Class的字节码文件Class _clazz = Class.forName(_classPath);//根据字节码文件进行实例化Object _object = _clazz.newInstance();Field[] _fields = _clazz.getDeclaredFields();setMember(_object, element, _fields);return _object;}/*** 设置成员变量* @param object* @param element* @param fields 成员变量数组*/private static void setMember(Object object, Element element, Field[] fields) {//获取当前Element获得的子节点迭代器Iterator<Element> _elements = element.elementIterator();while(_elements.hasNext()){Element _childElement = _elements.next();//当前正在设置的成员变量Field _field = null;//获取变量类型String _type = _childElement.getName();//获取变量名String _name = _childElement.attributeValue("name");//获取变量值String _value = _childElement.getTextTrim();//找到当前正在设置的成员变量for(int i = 0;i < fields.length;i ++ ){if(fields[i].getName().equals(_name)){_field = fields[i];break;}}if(_field == null){throw new RuntimeException("没找到该成员变量" + _name);}//此时可以访问私有成员变量_field.setAccessible(true);if(!setBaseTypeMember(object, _field, _type, _value)){//当前成员变量不是基本类型,则为引用类型成员变量
                setReferenceTypeMember(_childElement, object,  _field);}}}/*** 设置引用类型成员变量* @param element* @param object* @param field*/@SuppressWarnings({ "rawtypes", "unchecked" })private static void setReferenceTypeMember(Element element, Object object,  Field field) {try {//若为list,则表示当前元素为一个list集合String _memberType = element.attributeValue("type");if(_memberType.equals("list")){List _list = new ArrayList();Iterator<Element> _iterator = element.elementIterator();while(_iterator.hasNext()){Element _childEle = _iterator.next();//递归获取该元素,并加入集合中Object _entity = getEntity(_childEle);_list.add(_entity);}field.set(object, _list);return;}//单元素的引用类型Object _entity = getEntity(element);field.set(object, _entity);} catch (Exception e) {throw new RuntimeException(e);}}/*** 设置基本类型成员变量* @param object* @param field* @param type* @param value* @return*/private static boolean setBaseTypeMember(Object object, Field field,String type, String value) {try {if(type.equals("Int")){//int型成员变量
                field.setInt(object, Integer.parseInt(value));}else if(type.equals("Double")){//double型成员变量
                field.setDouble(object, Double.parseDouble(value));}else if(type.equals("Float")){//float型成员变量
                field.setFloat(object, Float.parseFloat(value));}else if(type.equals("Long")){//long型成员变量
                field.setLong(object, Long.parseLong(value));}else if(type.equals("Char")){//char型成员变量field.setChar(object, value.charAt(0));}else if(type.equals("String")){//string型成员变量
                field.set(object, value);}else{return false;}} catch (Exception e) {throw new RuntimeException(e);}return true;}/*** @Title: init* @Description: TODO 初始化,将XML读入内存* @param xmlPath* @return Document节点* @throws FileNotFoundException* @return: Document*/private static Document init(String xmlPath) throws FileNotFoundException {//获取XML文件路径.是根据当前classPath去寻找,例如文件a.xml是放在根目录下,则需要输入的路径便是a.xml//还有另外一种方法是通过class.getResource("/" + xmlPath)效果是一样的//关于java中的路径问题还是没有搞得很清楚,下来还需要多看String _filePath = XMLUtil.class.getClassLoader().getResource(xmlPath).getPath();File _file = new File(_filePath);//如果文件存在if(_file.exists()){//利用dom4j返回该XML的documentSAXReader _reader = new SAXReader();try {Document _document = _reader.read(_file);return _document;} catch (DocumentException e) {e.printStackTrace();}}else{throw new FileNotFoundException("您输入的XML文件地址未查到");}return null;}}

测试方法

    @Testpublic void testXMLUtil() throws Exception{System.out.println(XMLUtil.toEntity("Class.xml"));}

结果输出

Ok,测试成功

代码已经更新至GitHub

·总结一下:

1.下回再也不写那么逗的Util了,每次写Util之前先思考思考如何才能写成一个自己以后还能用到的真正的工具类。

2.对于这个版本自己还是有一些不满意的地方,每个成员变量我都是在XML文件里面声明了它的类型,比如<String ...>,既然我都已经通过反射拿到了成员变量的数组,为什么不用成员变量对象去判断它的类型呢??这个是可以改进的地方。

3.这次变量命名和注释相较于上一次已经有了很大的进步,自己还是比较满意的。

4.有什么理由可以不努力呢??哈哈

转载于:https://www.cnblogs.com/a294098789/p/5343172.html

上次遗留下来的XMLUtil的问题相关推荐

  1. 如何删除windows服务zz 重新安装PostgreSQL时删除上次遗留service的方法

    如何删除windows服务2006-10-10 11:09     作者:网络安全日志( www.nslog.cn ) 日期:2006/10/10  ( 转载请保留此申明) 一.什么是Windows服 ...

  2. php amp 字符串处理,php字符串处理之全角半角转换

    半角全角的处理是字符串处理的常见问题,本文尝试为大家提供一个思路. 一.概念 全角字符unicode编码从65281~65374 (十六进制 0xFF01 ~ 0xFF5E) 半角字符unicode编 ...

  3. linux gzip和tar一起用,Linux下压缩工具gzip和归档工具tar及其实战shell应用

    Linux下压缩工具gzip和归档工具tar及其实战shell应用 第一章:gzip的使用技巧 gzip [option]... file... -d: 解压缩,相当于gunzip; -#: 指定压缩 ...

  4. Linux编译安装qt5.9,Linux CentOS7 安装 Qt 5.9.2

    Linux CentOS7 安装 Qt 5.9.2 参考链接 http://doc.qt.io/qt-5/linux.html sudo yum groupinstall "C Develo ...

  5. oracle删除表不等待,oracle故障处理之删除大表空间hang住

    背景 数据库分区表数据越来越大,需要对过期话的数据进行迁移,以及大的分区表需要进行数据的清理和删除,达到释放磁盘空间的目的. 问题说明 环境:linux 6.X 数据库:oracle 11.2.0.4 ...

  6. 应用服务器与WSGI协议以及flask后端框架总结(后端接收请求返回响应的整个流程)...

    上次遗留了两个问题,先说一下自己的看法 问题: 1.明明一个线程只能处理一个请求,那么栈里的元素永远是在栈顶,那为什么需要用栈这个结构?用普通变量不行吗. 2._request_ctx_stack和_ ...

  7. python基础之socket编程

    阅读目录 一 客户端/服务器架构 二 osi七层 三 socket层 四 socket是什么 五 套接字发展史及分类 六 套接字工作流程 七 基于TCP的套接字 八 基于UDP的套接字 九 粘包现象 ...

  8. FPGA之道(69)提高设计的综合性能(一)提高设计的鲁棒性

    文章目录 前言 提高设计的鲁棒性 一些影响设计正常工作的原因 非法输入 环境干扰 应对方法之输入预处理 应对方法之RAM替换FIFO 应对方法之状态机超时跳转 应对方法之三模冗余 应对方法之全局复位 ...

  9. mongodb分享(二)

    上次讲的:查询find\findone\pretty.条件操作符 (大于.小于.大于等于.小于等于.不等于,$type).limit\skip.sort.Db.postjson.getIndexes( ...

  10. JSONAssert Spring Boot Test

    2019独角兽企业重金招聘Python工程师标准>>> JSONAssert 本此测试用例正确的原始顺序为(需求见POST) Body = [{"driver": ...

最新文章

  1. 文本分类之特征简约算法说明
  2. ecplise tomcat启动报错
  3. cod16 服务器正在维护,使命召唤16玩不了怎么办 使命召唤16进不去解决方法
  4. 拜托!程序员的工作不能用时间来衡量
  5. msp430入门编程21
  6. Soul 网关源码阅读(二)代码初步运行
  7. Chrome 终究走上了 IE 6 的老路
  8. BZOJ3994[SDOI2015] 约数个数和
  9. Kaggle Tweet Sentiment Extraction竞赛
  10. 10个网站为初学者学习JavaScript
  11. Java开发环境及其特点
  12. JAVA广度优先搜索---寻找从A点到B点最短路径
  13. GWO-KELM和GWO-SVR代码实现
  14. 典型集与Shannon信源编码理论
  15. 关于Python 统计出log文件 各个类型的大小总和
  16. 名词解释:DNS,A记录,子域名,CNAME别名,PTR,MX,TXT,SRV,TTL
  17. 王者荣耀 是什么语言编写的
  18. 网络问题解决—电脑能上网(QQ微信和浏览器一级网页)但浏览器打不开二级网页
  19. 鸿蒙系统怎么退出,华为鸿蒙2.0系统升级了怎么退回EMUI11系统?操作教程详解[多图]...
  20. H2 数据库入门和基本使用

热门文章

  1. Bzoj 3339: Rmq Problem Bzoj 3585: mex 莫队,树状数组,二分
  2. .plist 中各个key的含义
  3. 【转】【开源专访】谢宝友:会说话的Linux内核
  4. 转载]2LIS_03_BX数据源和CUBE之间不能垫DSO的原因
  5. WordPress SEO 完全指南
  6. json的的解析方法
  7. 如何才能成为优秀的架构师?
  8. 掌握3分钟网络排障秘技,网络管理员不再做“苦命人”
  9. 华为matepad使用鸿蒙系统,首发鸿蒙系统!华为MatePad采用骁龙+麒麟双芯片版本,哪款更香?...
  10. KNN (K近邻算法) - 识别手写数字