利用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完成,类 ...
随机推荐
- iOS-#ifdef DEBUG代码块介绍
iOS-#ifdef DEBUG宏定义介绍 一.#ifdef DEBUG代码块 #ifdef DEBUG // Debug 模式的代码... #else // Release 模式的代码... #en ...
- xslt中的常用函数
在我们制作标签的时候经常要使用到一些xslt的知识,以下整理了常用的xslt函数供大家使用. 常用字符串函数: contains('Welcome','e'):字符串包含,包含:true,不包含:fa ...
- android开发之调试技巧 分类: android 学习笔记 2015-07-18 21:30 140人阅读 评论(0) 收藏
我们都知道,android的调试打了断点之后运行时要使用debug as->android application 但是这样的运行效率非常低,那么我们有没有快速的方法呢? 当然有. 我们打完断点 ...
- titlebar和actionbar上的按钮设置
---恢复内容开始--- Actionbar加按钮: 在res文件夹下新建menu文件夹(如果你没有),然后添加一个XML文件 <?xml version="1.0" enc ...
- React组件的生命周期各环节运作流程
'use strict'; React.createClass({ //1.创建阶段 getDefaultProps:function(){ //在创建类的时候被调用 console.log('get ...
- java编程思想-异常
DynamicFields类的setField方法里面的getField方法抛出的异常NoSuchFieldException 为什么是throw new RuntimeException(e);
- ftp不能上传解决办法
自己的服务器,然后我分好ftp,有一天,有个客户要传东西,发现怎么也传不上,但是可以下载,,,,弄了半天,目录权限也是完全访问,但还是不行,原来是serv-u分配的空间小了啊,所以只能下载不能上传.. ...
- C#线程池ThreadPool.QueueUserWorkItem接收线程执行的方法返回值
最近在项目中需要用到多线程,考虑了一番,选择了ThreadPool,我的需求是要拿到线程执行方法的返回值, 但是ThreadPool.QueueUserWorkItem的回调方法默认是没有返回值的,搜 ...
- 那些常用的eclipse快捷键
用了很久的eclipse了,有些快捷键常用,有的偶尔使用,现在记下常用的快捷键,以便大家和自己查用(持续更新) 这些快捷键都可以在[window]-[preferences]-[general]-[k ...
- 【转】iOS25彩票 幸运转盘
原文 : http://www.it165.net/pro/html/201409/21216.html 最终效果图: 各个view的关系图: 背景圆盘(需穴ky"http://www.it ...