对于一些小批量的数据,如果采用数据库来存取的话,未免有点大题小作,使用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到对象的解析的更多相关文章

  1. 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

    作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...

  2. 利用JAVA反射机制设计通用的DAO

    利用JAVA反射机制设计一个通用的DAO 反射机制 反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字,    那么就可以通过反射机制来获得类的所有信息. 反射机制创建类对象 ...

  3. 利用Java反射机制对实体类的常用操作工具类ObjectUtil

    代码: ObjectUtil类: import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.Simpl ...

  4. 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】

    方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; priva ...

  5. 利用Java反射机制将Bean转成Map

    import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...

  6. 利用java反射机制实现读取excel表格中的数据

    如果直接把excel表格中的数据导入数据库,首先应该将excel中的数据读取出来. 为了实现代码重用,所以使用了Object,而最终的结果是要获取一个list如List<User>.Lis ...

  7. 利用JAVA反射机制将JSON数据转换成JAVA对象

    net.sf.json.JSONObject为我们提供了toBean方法用来转换为JAVA对象, 功能更为强大,  这里借鉴采用JDK的反射机制, 作为简单的辅助工具使用,   有些数据类型需要进行转 ...

  8. 不使用BeanUtils,利用Java反射机制:表单数据自动封装到JavaBean

    在百度搜“java反射 将表单数据自动封装到javabean ”,第一页显示的都是一样的代码,都是利用导入第三方jar包<commons-beanutils>和<commons-lo ...

  9. Java反射机制(创建Class对象的三种方式)

    1:了解什么是反射机制? 在通常情况下,如果有一个类,可以通过类创建对象:但是反射就是要求通过一个对象找到一个类的名称:   2:在反射操作中,握住一个核心概念: 一切操作都将使用Object完成,类 ...

随机推荐

  1. 观察者模式在ng(Angular)中的应用

    在这个前端框架满天飞的天下,angular MVVM 的模式确实火了一把,所以最近一直在学习ng,感悟颇多,填坑无数,今天终静下心来打算更新自己久未变动的博客,做一做总结. 1.在ng中的观察者模式: ...

  2. shell入门之函数应用 分类: 学习笔记 linux ubuntu 2015-07-10 21:48 77人阅读 评论(0) 收藏

    最近在学习shell编程,文中若有错误的地方还望各位批评指正. 先来看一个简单的求和函数 #!/bin/bash #a test about function f_sum 7 8 function f ...

  3. frame模型

    #import "CZWeiboFrame.h" #import "CZWeibo.h" @implementation CZWeiboFrame #defin ...

  4. linux下杀死进程(kill)的N种方法 【转】

    转自 http://blog.csdn.net/andy572633/article/details/7211546 首先,用ps查看进程,方法如下: $ ps -ef ……smx       182 ...

  5. 如何在单元测试中测试异步函数,block回调这种

    大概有四种方法: runloop 阻塞主进程等待结果 semphaore 阻塞主进程等待结果 使用XCTestExpectation 阻塞主线程等待(我用这个,xcode自带的,为啥不用) 使用第三方 ...

  6. codevs 1519 过路费 最小生成树+倍增

    /*codevs 1519 过路费 最小生成树+倍增*/ #include<iostream> #include<cstdio> #include<cstring> ...

  7. HDFS的Java客户端操作代码(查看HDFS下所有的文件或目录)

    1.查看HDFS下所有的文件或目录 package Hdfs; import java.io.IOException; import java.net.URI; import org.apache.h ...

  8. 单元测试--------Assert

      名称 说明 AreEqual(Object, Object) 验证指定的两个对象是否相等. 如果两个对象不相等,则断言失败. AreEqual(Double, Double, Double) 验证 ...

  9. 实现正在加载中界面的Android库:DynamicBox

    转载. DynamicBox是一个Android库,能够inflates自定义布局来指示出: 正在加载内容 显示一个异常 或者是一个自定义视图     项目主页:http://www.open-ope ...

  10. Sql server 数据库中,纯SQL语句查询、执行 单引号问题。

    在默认值情况下, select 'abc',Titile from tb_Name;  ---输出内容 是abc: 如果想输出 单引号 'abc,需要使用select '''abc',Titile f ...