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

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

Student(学生类)

  1. package com.taoyuan.entity.custom;
  2.  
  3. /**
  4. * @ClassName: Student
  5. * @Description: TODO Student实体类设计
  6. * @author: Han
  7. * @date: 2016-3-31 下午4:54:04
  8. */
  9. public class Student {
  10.  
  11. private int id;
  12. private String name;
  13.  
  14. public int getId() {
  15. return id;
  16. }
  17. public void setId(int id) {
  18. this.id = id;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26.  
  27. @Override
  28. public String toString() {
  29.  
  30. return "this student`s id is " + this.id + " and name is " + this.name;
  31. }
  32. }

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

  1. package com.taoyuan.entity.custom;
  2.  
  3. import java.util.List;
  4.  
  5. /**
  6. * @ClassName: Class
  7. * @Description: TODO Class班级实体类设计
  8. * @author: Han
  9. * @date: 2016-3-31 下午4:58:21
  10. */
  11. public class Class {
  12.  
  13. private int id;
  14. private String className;
  15. private List<Student> student;
  16.  
  17. public int getId() {
  18. return id;
  19. }
  20. public void setId(int id) {
  21. this.id = id;
  22. }
  23. public String getClassName() {
  24. return className;
  25. }
  26. public void setClassName(String className) {
  27. this.className = className;
  28. }
  29. public List<Student> getStudents() {
  30. return student;
  31. }
  32. public void setStudents(List<Student> student) {
  33. this.student = student;
  34. }
  35.  
  36. @Override
  37. public String toString() {
  38.  
  39. return "This class`s id is " + this.id + " and name is " + this.className
  40. + "\t\nit`s students are " + this.student;
  41. }
  42. }

XML文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Entity>
  3. <Class classPath="com.taoyuan.entity.custom.Class">
  4.  
  5. <Int name="id">1</Int>
  6. <String name="className">软件工程</String>
  7. <Student name="student" type="list">
  8.  
  9. <!-- Student数组 -->
  10. <Student classPath="com.taoyuan.entity.custom.Student">
  11. <Int name="id">1</Int>
  12. <String name="name">李明</String>
  13. </Student>
  14. <Student classPath="com.taoyuan.entity.custom.Student">
  15. <Int name="id">2</Int>
  16. <String name="name">狗蛋</String>
  17. </Student>
  18. </Student>
  19. </Class>
  20. </Entity>

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

  1. package com.taoyuan.utils;
  2.  
  3. import java.io.File;
  4. import java.io.FileNotFoundException;
  5. import java.lang.reflect.Field;
  6. import java.util.ArrayList;
  7. import java.util.Iterator;
  8. import java.util.List;
  9.  
  10. import org.dom4j.Document;
  11. import org.dom4j.DocumentException;
  12. import org.dom4j.Element;
  13. import org.dom4j.io.SAXReader;
  14.  
  15. /**
  16. * @ClassName: XMLUtil
  17. * @Description: TODO XML工具类
  18. * @author: Han
  19. * @date: 2016-3-22 下午3:09:03
  20. */
  21. public class XMLUtil {
  22.  
  23. /**
  24. * @Title: toEntity
  25. * @Description: TODO 将XML文件转换为一个entity
  26. * @param xmlPath
  27. * @return
  28. * @throws Exception
  29. * @return: Object
  30. */
  31. public static Object toEntity(String xmlPath) throws Exception{
  32.  
  33. //初始化,将XML文件读入内存,生成Document
  34. Document _document = init(xmlPath);
  35.  
  36. //获取根目录节点
  37. Element _rootEle = _document.getRootElement();
  38. String _rootName = "";
  39.  
  40. if(_rootEle != null){
  41.  
  42. //根目录节点名字
  43. _rootName = _rootEle.getName();
  44. }
  45.  
  46. if(!_rootName.equals("Entity")){
  47.  
  48. throw new Exception("请确认根节点名字是否为Entity");
  49. }
  50.  
  51. List<Element> elements = _rootEle.elements();
  52.  
  53. //在Entity节点中无子节点
  54. if(elements.size() == 0){
  55.  
  56. return null;
  57. }
  58.  
  59. return getEntity(elements.get(0));
  60. }
  61.  
  62. /**
  63. * 获取根据节点Element获取对应的Entity
  64. * @param element
  65. * @return
  66. * @throws ClassNotFoundException
  67. * @throws InstantiationException
  68. * @throws IllegalAccessException
  69. */
  70. @SuppressWarnings("rawtypes")
  71. private static Object getEntity(Element element)
  72. throws ClassNotFoundException, InstantiationException,
  73. IllegalAccessException {
  74.  
  75. //获取classPath
  76. String _classPath = element.attributeValue("classPath");
  77.  
  78. //获取Class的字节码文件
  79. Class _clazz = Class.forName(_classPath);
  80. //根据字节码文件进行实例化
  81. Object _object = _clazz.newInstance();
  82.  
  83. Field[] _fields = _clazz.getDeclaredFields();
  84.  
  85. setMember(_object, element, _fields);
  86.  
  87. return _object;
  88. }
  89.  
  90. /**
  91. * 设置成员变量
  92. * @param object
  93. * @param element
  94. * @param fields 成员变量数组
  95. */
  96. private static void setMember(Object object, Element element, Field[] fields) {
  97.  
  98. //获取当前Element获得的子节点迭代器
  99. Iterator<Element> _elements = element.elementIterator();
  100. while(_elements.hasNext()){
  101.  
  102. Element _childElement = _elements.next();
  103.  
  104. //当前正在设置的成员变量
  105. Field _field = null;
  106. //获取变量类型
  107. String _type = _childElement.getName();
  108.  
  109. //获取变量名
  110. String _name = _childElement.attributeValue("name");
  111. //获取变量值
  112. String _value = _childElement.getTextTrim();
  113.  
  114. //找到当前正在设置的成员变量
  115. for(int i = 0;i < fields.length;i ++ ){
  116.  
  117. if(fields[i].getName().equals(_name)){
  118.  
  119. _field = fields[i];
  120. break;
  121. }
  122. }
  123.  
  124. if(_field == null){
  125.  
  126. throw new RuntimeException("没找到该成员变量" + _name);
  127. }
  128.  
  129. //此时可以访问私有成员变量
  130. _field.setAccessible(true);
  131.  
  132. if(!setBaseTypeMember(object, _field, _type, _value)){
  133.  
  134. //当前成员变量不是基本类型,则为引用类型成员变量
  135. setReferenceTypeMember(_childElement, object, _field);
  136. }
  137. }
  138. }
  139.  
  140. /**
  141. * 设置引用类型成员变量
  142. * @param element
  143. * @param object
  144. * @param field
  145. */
  146. @SuppressWarnings({ "rawtypes", "unchecked" })
  147. private static void setReferenceTypeMember(Element element, Object object, Field field) {
  148.  
  149. try {
  150. //若为list,则表示当前元素为一个list集合
  151. String _memberType = element.attributeValue("type");
  152.  
  153. if(_memberType.equals("list")){
  154.  
  155. List _list = new ArrayList();
  156.  
  157. Iterator<Element> _iterator = element.elementIterator();
  158. while(_iterator.hasNext()){
  159.  
  160. Element _childEle = _iterator.next();
  161.  
  162. //递归获取该元素,并加入集合中
  163. Object _entity = getEntity(_childEle);
  164. _list.add(_entity);
  165. }
  166.  
  167. field.set(object, _list);
  168. return;
  169. }
  170.  
  171. //单元素的引用类型
  172. Object _entity = getEntity(element);
  173. field.set(object, _entity);
  174. } catch (Exception e) {
  175.  
  176. throw new RuntimeException(e);
  177. }
  178. }
  179.  
  180. /**
  181. * 设置基本类型成员变量
  182. * @param object
  183. * @param field
  184. * @param type
  185. * @param value
  186. * @return
  187. */
  188. private static boolean setBaseTypeMember(Object object, Field field,
  189. String type, String value) {
  190.  
  191. try {
  192. if(type.equals("Int")){
  193.  
  194. //int型成员变量
  195. field.setInt(object, Integer.parseInt(value));
  196. }else if(type.equals("Double")){
  197.  
  198. //double型成员变量
  199. field.setDouble(object, Double.parseDouble(value));
  200. }else if(type.equals("Float")){
  201.  
  202. //float型成员变量
  203. field.setFloat(object, Float.parseFloat(value));
  204. }else if(type.equals("Long")){
  205.  
  206. //long型成员变量
  207. field.setLong(object, Long.parseLong(value));
  208. }else if(type.equals("Char")){
  209.  
  210. //char型成员变量
  211. field.setChar(object, value.charAt(0));
  212. }else if(type.equals("String")){
  213.  
  214. //string型成员变量
  215. field.set(object, value);
  216. }else{
  217.  
  218. return false;
  219. }
  220. } catch (Exception e) {
  221.  
  222. throw new RuntimeException(e);
  223. }
  224.  
  225. return true;
  226. }
  227.  
  228. /**
  229. * @Title: init
  230. * @Description: TODO 初始化,将XML读入内存
  231. * @param xmlPath
  232. * @return Document节点
  233. * @throws FileNotFoundException
  234. * @return: Document
  235. */
  236. private static Document init(String xmlPath) throws FileNotFoundException {
  237.  
  238. //获取XML文件路径.是根据当前classPath去寻找,例如文件a.xml是放在根目录下,则需要输入的路径便是a.xml
  239. //还有另外一种方法是通过class.getResource("/" + xmlPath)效果是一样的
  240. //关于java中的路径问题还是没有搞得很清楚,下来还需要多看
  241. String _filePath = XMLUtil.class.getClassLoader().getResource(xmlPath).getPath();
  242.  
  243. File _file = new File(_filePath);
  244.  
  245. //如果文件存在
  246. if(_file.exists()){
  247.  
  248. //利用dom4j返回该XML的document
  249. SAXReader _reader = new SAXReader();
  250.  
  251. try {
  252.  
  253. Document _document = _reader.read(_file);
  254.  
  255. return _document;
  256.  
  257. } catch (DocumentException e) {
  258.  
  259. e.printStackTrace();
  260. }
  261. }else{
  262.  
  263. throw new FileNotFoundException("您输入的XML文件地址未查到");
  264. }
  265.  
  266. return null;
  267. }
  268.  
  269. }

测试方法

  1. @Test
  2. public void testXMLUtil() throws Exception{
  3.  
  4. System.out.println(XMLUtil.toEntity("Class.xml"));
  5. }

结果输出

Ok,测试成功

代码已经更新至GitHub

·总结一下:

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

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

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

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

上次遗留下来的XMLUtil的问题的更多相关文章

  1. 从DOM操作看Vue&React的前端组件化,顺带补齐React的demo

    前言 接上文:谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo 上次写完博客后,有朋友反应第一内容有点深,看着迷迷糊糊:第二是感觉没什么使用场景,太过业务化,还不如直接写Vue ...

  2. python网络编程

    Socket是网络编程的一个抽象的概念. 通常我们用一个Socket表示"打开了一个网络链接",而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可. 套 ...

  3. C阶段【01】 - C基础

    一.进制 进位方法:逢几进一(也就是几进制) 举例:十进制 12  :  二进制  0b(计算机前缀)  0b1011  :  八进制  0   073  :十六进制  0x  0xABCDEF 十进 ...

  4. iOS应用架构谈 网络层设计方案

    网络层在一个App中也是一个不可缺少的部分,工程师们在网络层能够发挥的空间也比较大.另外,苹果对网络请求部分已经做了很好的封装,业界的AFNetworking也被广泛使用.其它的ASIHttpRequ ...

  5. ectouch第十讲 之ecshop中 dwt, lbi 文件详解

    原文:http://www.yunmoban.cn/article-241.html Ecshop包括的文件夹有admin.api.cert.data.images.includes.js. lang ...

  6. Web开发从零单排之二:在自制电子请帖中添加留言板功能,SAE+PHP+MySql

    在上一篇博客中介绍怎样在SAE平台搭建一个html5的电子请帖网站,收到很多反馈,也有很多人送上婚礼的祝福,十分感谢! web开发从零学起,记录自己学习过程,各种前端大神们可以绕道不要围观啦 大婚将至 ...

  7. 修改ecshop模板体会

    在上一篇中给大家带来了ecshop的总体的框架.从总体上看ecshop,相信大家的思路应该很清楚.作为一个对开源项目修改者你来说,能对ecshop有个初步的了解就行了,下面我会给大家带来我在修改ecs ...

  8. [转] iOS应用架构谈 网络层设计方案

    原文地址:http://casatwy.com/iosying-yong-jia-gou-tan-wang-luo-ceng-she-ji-fang-an.html iOS应用架构谈 开篇 iOS应用 ...

  9. 需要我们了解的SQL Server阻塞原因与解决方法

    需要我们了解的SQL Server阻塞原因与解决方法 上篇说SQL Server应用模式之OLTP系统性能分析.五种角度分析sql性能问题.本章依然是SQL性能 五种角度其一“阻塞与死锁” 这里通过连 ...

随机推荐

  1. flexbox弹性伸缩布局

    <!doctype html><html lang="en"><head> <meta charset="UTF-8" ...

  2. spring中的Log4jConfigListener作用和webapp.root的设置

    转:http://blog.sina.com.cn/s/blog_7bbf356c01016wld.html 使用spring中的Log4jConfigListener有如如下好处:     1. 动 ...

  3. bzoj2154(莫比乌斯反演)

    又是一道经典题. 1.学习了下O(n) 的做法. // // main.cpp // bzoj2154 // // Created by New_Life on 16/7/7. // Copyrigh ...

  4. html中盒子模型立体结构图

    边框(border),位于盒子的第一层..元素内容(content).内边距(padding),两者同位于第二层..背景图(background-image),位于第三层..背景色(backgroun ...

  5. java 字符串 转码

    //xmlStr 为需要转码的字符串 UTF-8 可改为不同的编码格式 如:GBK //亲测可用 仅供参考 String xmlStrs=""; try{ xmlStrs=new ...

  6. Spring框架的反序列化远程代码执行漏洞分析(转)

    欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...

  7. JSF框架认识

    JSF框架 编辑 JavaServer Faces (JSF) 是一种用于构建Java Web 应用程序的标准框架(是Java Community Process 规定的JSR-127标准).它提供了 ...

  8. js解码

    如代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...

  9. 初学java之触发响应事件举例子

    设置一个触发响应事件? 比如消息框..... package hello; import javax.swing.*; import project.readerListen; import java ...

  10. Asp.net 解析json

    Asp.net Json数据解析的一种思路 http://www.cnblogs.com/scy251147/p/3317366.html http://tools.wx6.org/json2csha ...