热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

适时开始自己写工具吧,骚年——XML和对象的转化

在导入导出的时候,我们可以选用excel、xml。但当出现父子结构的样子时,用excel来处理未免就有点乏力了。这里就需要用更强大的xml来进行处理了。下面

        在导入导出的时候,我们可以选用excel、xml。

        但当出现父子结构的样子时,用excel来处理未免就有点乏力了。这里就需要用更强大的xml来进行处理了。下面看下这个xml的结构吧。

        





	
		
		
			
			
			
		
	

	
		
		
			
			
			
		
	

          那么对应要转成的对象是什么样子呢?

public class Tree{
	private String id;
	private String name;
	private T parent;
	private Listchildren;
	private boolean isleaf;
}
public class Module extends Tree{
	private String url;	
	private String description;
	private String sn;
	private Integer priority = 99;
	private List permissions ;
	private String organizationid;
}

          现在要通过xml进行导入,xml中写的page和module都是Module类型的。

方法一:

         通过dom4j,获取每个Element,然后对Attribute进行取,如(程序用到的代码较多,我只写一下核心部分):

Document dom=new SAXReader().read("读的xml文件");
List moduleXML=dom.selectNodes("/system/module");
List modules=new ArrayList();
for(Iteartor moduleIter=moduleXML.iteartor();moduleIter.hasNext();){
	Element moduleEle=moduleIter.next();
	Module module=new Module();
	module.setName(moduleEle.attribute("name"));
	module.setSn(moduleEle.attribute("sn"));
	module.setPriority(Integer.parseInt(moduleEle.attribute("priority")));
	……
	List pageXML=moduleEle.elements("page");
	List pages=new ArrayList();
	for(Iteartor pageIter=pageXML.iteartor();pageIter.hasNext();){
		Element pageEle=pageIter.next();
		Module page=new Module();
		page.setName(pageEle.attribute("name"));
		page.setSn(pageEle.attribute("sn"));
		page.setPriority(Integer.parseInt(pageEle.attribute("priority")));
		……
		pages.add(page);
	}
	module.setChildren(pages);
	modules.add(module);
}

          你是否看出了上面代码的坏味道呢?

         1.代码重复

         2.如果对xml想对page加一个属性,那么还需要改代码

         现在我们需要做什么改变呢?跟着我来看看吧,还是反射的应用~

public class Dom2Object {
	public static Object transfAtt2Obj(Class clazz,Element element){
		Object obj = null;
		try {
			obj=clazz.newInstance();
			for (Iterator iterator = element.attributeIterator(); iterator.hasNext();) {
				Attribute attribute = (Attribute) iterator.next();
				setFieldValueInAllSuper(obj, attribute.getName(), attribute.getValue());
			}
		} catch (Exception e) {e.printStackTrace();}
		
		return obj;
	} 	
	private static void setFieldValueInAllSuper(Object obj, String propertyName,Object value){
		//获取当前Object的class
		Class claszz=obj.getClass();  
		Field field = null;  	  
		do{     
			try{  //从类里面获取指定属性
				field = claszz.getDeclaredField(propertyName);  
			}  
			catch(NoSuchFieldException e){//如果没有获取到,则设置为null
				field=null;  
			}
			//设置当前class为父class
			claszz=claszz.getSuperclass();  
		} while(field==null&&claszz!=null); //当field为空且class不为空时,进行下次循环
		
		//如果field为空,说明没有此字段,返回空
		if(field==null) return;  
		//如果不为空,设置可见性,然后返回
		field.setAccessible(true);
		try {
			//将要赋的值转到实体需要的类型,不然会报异常(例如String转Integer)
			Object val;
			//通过获取字段类型的构造函数来完成此操作(字段类型必须是包装类哦)
			val = field.getType().getConstructor(String.class).newInstance(value);
			field.set(obj, val);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

          首先,是写一个为对象某属性赋值的方法,而属性是通过反射得到的。然后通过dom4j里的Attribute的API获取name和value,这样就可以动态的为对象的参数进行赋值了。

         现在来看下进行方法提取后,之类的那些重复代码会变成什么样:

Document dom=new SAXReader().read("读的xml文件");
List moduleXML=dom.selectNodes("/system/module");
List modules=new ArrayList();
for(Iteartor moduleIter=moduleXML.iteartor();moduleIter.hasNext();){
	Element moduleEle=moduleIter.next();
	
	Module module=(Module)transfAtt2Obj(Module.class,moduleEle);
	
	List pageXML=moduleEle.elements("page");
	List pages=new ArrayList();
	for(Iteartor pageIter=pageXML.iteartor();pageIter.hasNext();){
		Element pageEle=pageIter.next();
		Module page=(Module)transfAtt2Obj(Module.class,pageEle);
		
		pages.add(page);
	}
	module.setChildren(pages);
	modules.add(module);
}

          应该很容易就看出来变化吧,那么这样写比前面那样写,优点在哪里呢?

         1.复用性强,只要别人转的xml的时候,对象的属性在xml中都是以某标签的属性形式存在(可以扩展成标签也可以),那么这个方法就可以重用,因为这个抽取的方法和业务逻辑一点关系也没有。

         2.扩展性好,一如前面说的,现在isleaf这个属性不必在xml中进行配置,但如果发现需要配置了,那么只需要在page这个标签的属性上加上isleaf="true"即可,代码可以完全不用动。

         这么看是好处多多,那么又该注意什么呢?

         1.用反射终究肯定会下降,不过当今时代的硬件,不用你考虑这个问题了

         2.对于不常封装的我们来说,可能会碰到各种各样的问题,写这个方法用的时间,你写循环其实早写完了。不过对于现在的我们来说,还是可以接受的,通过项目学习、巩固基础嘛~~

         3.自己写的工具类代码最好自己保留好,因为如果你看过我写的编程语言中的各种反射,你会发现

setFieldValueInAllSuper这个方法和那篇文章中的getFieldValueInAllSuper几乎一样,只不过一个是获取,一个是赋值。所以说代码经验的积累必不可少。

    4.把握好度,够用就好。记住,你不是在写一个类库,够你用就好了,不然你的项目就可能延期了。一如我们用

的是将属性写在xml标签中的属性的位置上,而不是将属性以标签的形式展现,所以我就可以不考虑那种情况,如果

再去做两种兼容,那么可能一天也未必能弄出来。

    5.嗅觉很重要,但见识更重要。一如曾经我们刚接触Java的时候,依然还记得将数据库中查出来的ResultSet

里面的值赋给一个对象,就是用的类似上面的方法。可当时还不知道反射可以这样做,所以也不觉得那样是重复。因

此,多看看项目源码,多学下人家的技巧是很有必要的。


总结:

    好的代码不是一次就写出来的,一如前面我是在写了之后,才觉得重复,然后才去改的。适当的重构自己的代

码,你会学到更多~~~

         



推荐阅读
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文介绍了Python对Excel文件的读取方法,包括模块的安装和使用。通过安装xlrd、xlwt、xlutils、pyExcelerator等模块,可以实现对Excel文件的读取和处理。具体的读取方法包括打开excel文件、抓取所有sheet的名称、定位到指定的表单等。本文提供了两种定位表单的方式,并给出了相应的代码示例。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
author-avatar
浪子一品香_938
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有