利用Java反射机制完成XML到对象的解析
对于一些小批量的数据,如果采用数据库来存取的话,未免有点大题小作,使用XML文件是个不错的方法,尤其是在一些Web应用中,经常需要缓存一部分数据,如果将这些数据形成XML文件,解析后放入一个Hashtable,那就能大大加快访问的速度。
由于工作的需要,写了一个解析工具,将XML解析成相应的对象列表。以下是源代码,希望对大家有所帮助,更希望大家帮我来改进这个工具。
package com.sp.util; /*
* author:hingwu
* email:hing3@163.com
* QQ:550598
* MSN:hing3wu@hotmail.com(很少开)
*/
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import exceptions.MyException; public class ParseXMLToObject {
public ParseXMLToObject(){} @SuppressWarnings("unchecked")
public List getObject(String name,String path,String className){
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
dbf.setIgnoringElementContentWhitespace(true);
DocumentBuilder db=null;
Document doc=null;
InputStream is=null;
try {
List list=new ArrayList();
db=dbf.newDocumentBuilder();
is=new FileInputStream(this.getClass().getResource(path).getPath());
doc=db.parse(is);
//根据要取的对象名称获取相应的节点列表
NodeList nodes=doc.getElementsByTagName(name);
if(nodes==null){
throw new MyException("null nodes with tagName "+name);
}
for(int i=0;i<nodes.getLength();i++){
Element node=(Element) nodes.item(i);
Class cls=Class.forName(className);
Object obj=cls.newInstance();
//获取节点下的所有子节点
NodeList childs=node.getChildNodes();
if(childs==null){
throw new MyException("null childs! "+node);
}
for(int j=0;j<childs.getLength();j++){
if(!childs.item(j).getNodeName().equals("#text")){
Element child=(Element)childs.item(j);
String childName=child.getNodeName();
String type=child.getAttribute("type");
String value=child.getAttribute("value");
Object valueObj=typeConvert(type,value);
String methodName="set"+Character.toUpperCase(childName.charAt(0))+childName.substring(1);
System.out.println("methodName="+methodName+", class="+Class.forName(type));
Method method=cls.getMethod(methodName, Class.forName(type));
method.invoke(obj, new Object[]{valueObj});
} }
list.add(obj);
}
return list; } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} }

//此方法用于将一个字符串转换为相应的数据类型
@SuppressWarnings("deprecation")
public Object typeConvert(String className,String value){
if(className.equals("java.lang.String")){
return value;
}
else if(className.equals("java.lang.Integer")){
return Integer.valueOf(value);
}
else if(className.equals("java.lang.Long")){
return Long.valueOf(value);
}
else if(className.equals("java.lang.Boolean")){
return Boolean.valueOf(value);
}
else if(className.equals("java.util.Date")){
return new Date(value);
}
else if(className.equals("java.lang.Float")){
return Float.valueOf(value);
}
else if(className.equals("java.lang.Double")){
return Double.valueOf(value);
}else return null;
}
} Subject类的代码: package com.sp.pojo; public class Subject {
private String port;
private String servletName;
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getServletName() {
return servletName;
}
public void setServletName(String servletName) {
this.servletName = servletName;
}
public Subject(){}
@Override
public String toString() {
// TODO Auto-generated method stub
return port+","+servletName;
} }

附上我的XML文件 <?xml version="1.0" encoding="UTF-8"?>
<xml-body>
<subjects>
<port type="java.lang.String" value="4587"/>
<servletName type="java.lang.String" value="com.sp.servlets.Route" />
</subjects> <subjects>
<port type="java.lang.String" value="5687"/>
<servletName type="java.lang.String" value="com.sp.servlets.Route" />
</subjects> <security>
<userName type="java.lang.String" value="gogo"/>
<password type="java.lang.String" value="gogo" />
</security>
</xml-body> 自己写了一个测试类进行测试 /**
* author:hingwu
* email:hing3@163.com
* QQ:550598
* MSN:hing3wu@hotmail.com(很少开)
*
* 上午11:44:27
*/
package com.sp.test; import java.util.Iterator;
import java.util.List; import com.sp.util.ParseXMLToObject; public class TestParse {
public static void main(String[] args){
ParseXMLToObject pxt=new ParseXMLToObject();
// List list=(List)pxt.getObject("security","/cache.xml","com.sp.pojo.Security");
List list=(List)pxt.getObject("subjects","/cache.xml","com.sp.pojo.Subject");
Iterator it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
} }
} 由于我的这个工具主要是为了缓存数据来使用的,我同时还完成了缓存类Cache的代码: package com.sp.util; import java.io.File;
import java.util.Hashtable; public class Cache {
//cache用来放置各种需要缓存的数据
private static Hashtable cache=new Hashtable();
//lastModifyTime用于维护配置文件的最后修改时间,从而确定是直接从Cache读数据还是需要重新解析配置文件
private static long lastModifyTime; public Object getObject(String name,String path,String parseClass,String className){
//如果配置文件被修改过则直接解析文件,否则直接从cache中取得相应的对象
if(checkModifyTime(path)){
System.out.println("get Object from file");
return getObjectFromFile(name,path,className);
}
return getObjectFromCache(name);
} //直接从缓存中获取相应的对象
public Object getObjectFromCache(String name){
System.out.println("get Object from cache");
return cache.get(name);
} //解析配置文件获取相应的对象
@SuppressWarnings("unchecked")
public Object getObjectFromFile(String name,String path,String className){
String key="key";
synchronized(key){
ParseXMLToObject pxt=new ParseXMLToObject();
Object obj=pxt.getObject(name, path, className);
cache.put(name, obj);
return obj;
} } //判断配置文件是否被修改过
public boolean checkModifyTime(String path){
String absPath=this.getClass().getResource(path).getPath();
long time=(new File(absPath)).lastModified();
if(lastModifyTime==0L||time>lastModifyTime){
lastModifyTime=time;
return true;
}
return false;
}
} 每次通过Cache去获取Hashtable中的数据时,会先判断XML文件有没有被修改过,如果没有修改,则直接返回数据,有修改则解析XML文件后返回数据。 为了测试Cache类,专门写了一个Test类: /**
* author:hingwu
* email:hing3@163.com
* QQ:550598
* MSN:hing3wu@hotmail.com(很少开)
*
* 下午02:04:10
*/
package com.sp.test;
import java.util.Iterator;
import java.util.List; import com.sp.util.Cache; public class TestCache { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
System.out.println("第"+i+"次获取缓存数据:");
Cache cache=new Cache();
List list=(List)cache.getObject("subjects","/cache.xml", "com.sp.util.ParseXMLToObject", "com.sp.pojo.Subject");
Iterator it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} } } 这种缓存策略有个好处,那就是在应用运行的时候,我们可以随时修改XML文件,而不需要重启应用或重新布署。
利用Java反射机制完成XML到对象的解析的更多相关文章
- 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换
作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...
- 利用JAVA反射机制设计通用的DAO
利用JAVA反射机制设计一个通用的DAO 反射机制 反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 反射机制创建类对象 ...
- 利用Java反射机制对实体类的常用操作工具类ObjectUtil
代码: ObjectUtil类: import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.Simpl ...
- 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】
方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; priva ...
- 利用Java反射机制将Bean转成Map
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...
- 利用java反射机制实现读取excel表格中的数据
如果直接把excel表格中的数据导入数据库,首先应该将excel中的数据读取出来. 为了实现代码重用,所以使用了Object,而最终的结果是要获取一个list如List<User>.Lis ...
- 利用JAVA反射机制将JSON数据转换成JAVA对象
net.sf.json.JSONObject为我们提供了toBean方法用来转换为JAVA对象, 功能更为强大, 这里借鉴采用JDK的反射机制, 作为简单的辅助工具使用, 有些数据类型需要进行转 ...
- 不使用BeanUtils,利用Java反射机制:表单数据自动封装到JavaBean
在百度搜“java反射 将表单数据自动封装到javabean ”,第一页显示的都是一样的代码,都是利用导入第三方jar包<commons-beanutils>和<commons-lo ...
- Java反射机制(创建Class对象的三种方式)
1:了解什么是反射机制? 在通常情况下,如果有一个类,可以通过类创建对象:但是反射就是要求通过一个对象找到一个类的名称: 2:在反射操作中,握住一个核心概念: 一切操作都将使用Object完成,类 ...
随机推荐
- shell中trap捕获信号
信号是一种进程间通信机制,它给应用程序提供一种异步的软件中断,使应用程序有机会接受其他程序活终端发送的命令(即信号).应用程序收到信号后,有三种处理方式:忽略,默认,或捕捉.进程收到一个信号后,会检查 ...
- Android Camera开发:使用TextureView和SurfaceTexture预览Camera 基础拍照demo
Google自Android4.0出了TextureView,为什么推出呢?就是为了弥补Surfaceview的不足,另外一方面也是为了平衡GlSurfaceView,当然这是本人揣度的.关于Text ...
- SQL常用的语句和函数
order by 的数值型灵活使用 select * from table_a where order by decode(函数,'asc',1,'desc',-1)*jsny; 控制试图的访问时间: ...
- CentOS安装最新的Mysql版本
Step1: 检测系统是否自带安装mysql # yum list installed | grep mysql Step2: 删除系统自带的mysql及其依赖命令: # yum -y remove ...
- Unity3D 常用事件
这里总结一下U3D常用的一些事件 //按下事件,GetKeyDown //抬起事件,Input.GetKeyUp //长按事件,Input.GetKey //任意键按下事件,Input.anyKeyD ...
- Android中Cursor类的概念和用法
http://blog.sina.com.cn/s/blog_618199e60101fskp.html 使用过 SQLite数据库的童鞋对 Cursor 应该不陌生,加深自己和大家对Android ...
- SimpleDateFormat使用详解
http://blog.csdn.net/gubaohua/article/details/575488 public class SimpleDateFormat extends DateForma ...
- C# var
VAR 是3.5新出的一个定义变量的类型其实也就是弱化类型的定义VAR可代替任何类型编译器会根据上下文来判断你到底是想用什么类型的 至于什么情况下用到VAR 我想就是你无法确定自己将用的是什么类型就可 ...
- 主成份分析PCA
Data Mining 主成分分析PCA 降维的必要性 1.多重共线性--预测变量之间相互关联.多重共线性会导致解空间的不稳定,从而可能导致结果的不连贯. 2.高维空间本身具有稀疏性.一维正态分布有6 ...
- 自己制作精美的App Store 软件截屏
当用户搜索到App的时候,一般都会先看截图,如果截图效果不好,可能用户就不会下载. 不想自己辛苦写的认为还不错的软件,因为截图的原因,而降低了很多下载量吧. 轻轻松松做出这样高大上的截屏效果来. Sc ...