对于一些小批量的数据,如果采用数据库来存取的话,未免有点大题小作,使用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文件,而不需要重启应用或重新布署。