今天,复习黑马第6天学习的pull解析XML文档,结合第10天讲的JavaBean,突然了有了新的思考。
以下是我创建的XML文档:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!-- 定义一个演示文档,存储黑马的所有班级,以及每个班级的信息
利用XML的功能之一:XML用来表示生活中有关系的数据
-->
<
itheima
>
<
class
>
<
name
>Anroid70期</
name
>
<
teacher
>于俏</
teacher
>
<
time
>2015年6月21日</
time
>
<
count
>77</
count
>
</
class
>
<
class
>
<
name
>JavaEE70期</
name
>
<
teacher
>张子艺</
teacher
>
<
time
>2015年7月2日</
time
>
<
count
>83</
count
>
</
class
>
</
itheima
>
|
下面是XML解析的Java代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
//pull解析xml文档开始。。。。。
try
{
//第1步:导入pull解析的包,得到pull解析工厂对象
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//第2步:通过pull解析工厂得到pull解析器
XmlPullParser parser = factory.newPullParser();
//将XML文档的输入流引入pull解析器
InputStream in =
new
FileInputStream(
"D:\\HeiMa Dairy\\Other\\MyWorkSpace\\JDBCPractice\\WebRoot\\xml\\itheima.xml"
);
//指定解析器的输入流和编码集
parser.setInput(in,
"utf-8"
);
//第4步:开始解析
//创建一个List集合,用来存储javabean,javabean会封装班级信息。
List<HeiMaClass> hmClassList =
null
;
HeiMaClass hmClass =
null
;
int
type =
0
;
//标记解析的位置
while
((type = parser.getEventType())!= XmlPullParser.END_DOCUMENT)
//到了XML的文档末尾就结束解析
{
//得到标签名,以作相应的判断 。
String tagName = parser.getName();
//用switch来判断解析的具体位置,比对标签名,采取相应的操作。
switch
(type)
{
case
XmlPullParser.START_TAG:
//开始标签
if
(
"itheima"
.equals(tagName))
{
//创建封装班级javabean的集合对象
hmClassList =
new
ArrayList<HeiMaClass>();
}
else
if
(
"class"
.equals(tagName))
{
//创建班级javabean,以封装数据
hmClass =
new
HeiMaClass();
}
else
{
//得到标签内容,用来封装进javabean hmClass中去。
String tagText = parser.nextText();
//利用内省,直接用标签文本,也即Javabean的属性来获取对应
//写入方法来赋值。
try
{
//内省重要代码************ //构造一个PropertyDescriptor对象
PropertyDescriptor pd =
new
PropertyDescriptor
(tagName,hmClass.getClass());
//内省重要代码************ //得到属性的写入方法
Method writeMethod = pd.getWriteMethod();
try
{
//内省重要代码************ writeMethod.invoke(hmClass, tagText);
}
catch
(Exception e) {
e.printStackTrace();
}
}
catch
(IntrospectionException e) {
e.printStackTrace();
}
}
break
;
case
XmlPullParser.END_TAG:
//结束标签
if
(
"class"
.equals(tagName))
{
//将班级对象封装进List集合
hmClassList.add(hmClass);
}
break
;
}
parser.next();
}
//先在控制台上将List集合打印查看一下
for
(HeiMaClass cla : hmClassList)
{
System.out.println(cla.toString());
}
//将List集合写到Session域中,供请求页面获取输出
request.getSession().setAttribute(
"hmClassList2"
, hmClassList);
//转发到请求页面
request.getRequestDispatcher(
"/pra/jdbc.jsp"
).forward(request, response);
}
catch
(XmlPullParserException e) {
e.printStackTrace();
}
|
在设计代码的时候,我采用的是javabean封装数据,XML文档中class这个标签对应的javabean代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
//黑马班级类,用来演示pull解析XML,将XML中的班级数据封装到黑马班级类中。
public
class
HeiMaClass {
private
String name,teacher,time,count;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getTeacher() {
return
teacher;
}
public
void
setTeacher(String teacher) {
this
.teacher = teacher;
}
public
String getTime() {
return
time;
}
public
void
setTime(String time) {
this
.time = time;
}
public
String getCount() {
return
count;
}
public
void
setCount(String count) {
this
.count = count;
}
public
String toString()
{
return
this
.name +
":"
+
this
.teacher +
":"
+
this
.time +
":"
+
this
.count;
}
}
|
在用else if语句判断对应javabean中的属性标签名时,我发现继续都是用属性名对应的方法来封装数据。那么,有没有可能通过javabean的属性名称(即对应xml文档的标签名称),得到这个属性的set方法呢?
后来我看了一下张孝祥老师的高新技术最后几个视频,发现这个正是内省技术,于是众多的else if语句通过javabean就很轻松的完成了。内省的简单操作是通过java.beans下的PropertyDescriptor类来实现的,构造这个类的对象需传递属性名称和字节码文件,然后通过getWriteMethod即可得到属性对应的写入方法,然后利用反射的原理即可封装数据至javabean中。
-------------------------------------------------------------------------------------------
以前看了反射和内省,当时还是朦朦胧胧,不知道它们到底有什么了不起的。现在我慢慢地发现这些技术如果明白了话,真的是非常实用的,真的像老师所说的,可以让我们少写很多的代码。
同理,pull序列化(将内存中的集合、对象)写到xml文档中去,可以使用反射和内省来减写很多的代码。代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
//从域中得到List集合,hmClassList2。
List<HeiMaClass> hmClassList = (List<HeiMaClass>)request.getSession().getAttribute(
"hmClassList2"
);
//准备进行集合的序列化
try
{
//第1步:得到解析器工厂
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//第2步:从解析器工厂得到序列化的接口
XmlSerializer serializer = factory.newSerializer();
//第3步:将文件输出流引入到序列化的接口
OutputStream out =
new
FileOutputStream(
"C:\\Users\\LENOVO\\Desktop\\serializer.xml"
);
serializer.setOutput(out,
"utf-8"
);
//第4步:正式开始序列化
//1。生成文档声明和文档结束
serializer.startDocument(
null
,
true
);
//2.生成根标签<itheima>
serializer.startTag(
null
,
"itheima"
);
//3.遍历生成字标签
for
(HeiMaClass hmClass : hmClassList)
{
//4.生成班级的开始和结束标签
serializer.startTag(
null
,
"class"
);
//利用反射+内省技术,获取HeiMaClass这个javabean的所有属性,并获取它们的值写入xml文档。
Field[] fields = hmClass.getClass().getDeclaredFields();
//遍历字段
for
(Field field : fields)
{
//获取字段的属性名
String propertyName = field.getName();
//得到属性描述器
try
{
PropertyDescriptor pd =
new
PropertyDescriptor(propertyName,hmClass.getClass());
//通过属性描述器得到字段对应的读取方法,获取得它的值并写入XML文档。
Method readMethod = pd.getReadMethod();
//调用方法获取属性值
try
{
String propertyValue = (String)readMethod.invoke(hmClass);
//生成开始和结束标签,并插入标签文本。
serializer.startTag(
null
, propertyName);
serializer.text(propertyValue);
serializer.endTag(
null
, propertyName);
}
catch
(Exception e) {
e.printStackTrace();
}
}
catch
(IntrospectionException e) {
e.printStackTrace();
}
}
serializer.endTag(
null
,
"class"
);
}
serializer.endTag(
null
,
"itheima"
);
serializer.endDocument();
//序列化成功,返回一个提示信息到request域中去
request.setAttribute(
"tipXML"
,
"XML文档创建成功,已保存到桌面。"
);
}
catch
(XmlPullParserException e) {
//序列化失败,返回一个提示信息到request域中去,因为只想失败的一次请求提醒,所以不需要将提示写至session域中去。
request.setAttribute(
"tipXML"
,
"XML文档创建失败!"
);
e.printStackTrace();
}
finally
{
//转发至请求页面
request.getRequestDispatcher(
"/pra/jdbc.jsp"
).forward(request, response);
}
|
内省在WEB中的一个小小的应用,
比如在Servlet里获取请求参数,可以利用内省根据属性名获取属性方法,将属性赋值给JavaBean.
本文转自屠夫章哥 51CTO博客,原文链接:http://blog.51cto.com/4259297/1672205,如需转载请自行联系原作者