Merlin 的魔力: 将 JavaBean 组件状态序列化到 XML
2008-01-24 20:26
295 查看
级别: 初级 John Zukowski 2001 年 7 月 01 日
将 JavaBean 组件状态长期持久地保存在 XML 文档中的功能在 J2SE 的 1.4 版本中得到了实现。 Merlin 的魔力系列的这一部分向您展示如何使用新的
Merlin 的这个功能可以将 JavaBean 组件状态长期持久地保存在 XML 文档中。序列化工作适合短期编组的需要(对于 CORBA 和 RMI)或适合将状态信息保存在一个执行的 servlet 中。但是序列化会产生许多问题,包括类库版本或 Java 运行时环境方面的问题。新的
开始
开始时,我们需要定义一个我们要初始化、保存和重新创建的类。让我们定义一个带有以下 4 个属性的类:
测试分数的整数数组
只读
这个可变的属性类型集将演示编码器如何处理不同的数据类型。
清单1
package net.zukowski.ibm;
import java.awt.Point;
public class Sample {
private int[] scores;
private String name;
private Point seat;
public void setScores(int[] value) ...{
scores = value;
}
public void setScores(int value, int position) ...{
scores[position] = value;
}
public int[] getScores() ...{
return scores;
}
public int getScores(int position) ...{
return scores[position];
}
public float getAverage() ...{
float sum = 0;
int count = scores.length;
float avg;
if (count == 0) ...{
avg = -1;
} else ...{
for (int i = 0; i < count; i++) ...{
sum += scores[i];
}
avg = sum / count;
}
return avg;
}
public void setName(String value) ...{
name = value;
}
public String getName() ...{
return name;
}
public void setSeat(Point value) ...{
seat = value;
}
public Point getSeat() ...{
return seat;
}
public String toString() ...{
return getClass().getName() +
"[scores=" + asString(scores) +
",avg=" + getAverage() +
",name=" + name +
",seat=" + seat + "]";
}
private String asString(int[] array) ...{
StringBuffer buffer = new StringBuffer("[");
for (int i=0, n=array.length; i < n; i++) ...{
if (i != 0) ...{
buffer.append(",");
}
buffer.append(array[i]);
}
buffer.append("]");
return buffer.toString();
}
}...
有一个有用的
保存状态
有了用于保存的类,我们可以创建一个实例并使用
[b]清单 2. 创建一个实例并将其保存为 XML[/b]
// Create
Sample sample = new Sample();
sample.setScores(new int[] {100, 90, 75});
sample.setName("Gore");
sample.setSeat(new Point(5, 3));
// Save
XMLEncoder encoder = new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream("Sample.xml")));
encoder.writeObject(sample);
encoder.close();...
!!!注意:XMLEncoder的writeObject(Object o)方法的参数(o)的类型类必须是public的,否则会报Class sun.reflect.misc.Trampoline can not access a member of class XXX.XXX.XXX with modifiers "什么什么"
检查格式
当检查清单 3 所示的 XML 文件时,您会注意到如何读取格式是与输出在一起编码的,在本例中是与 v1.4 beta 中的
[b]清单 3. 经过编码的 XML 样本实例[/b]
[b]
?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.0-beta" class="java.beans.XMLDecoder">
<object class="net.zukowski.ibm.Sample">
<void property="name">
<string>Gore</string>
</void>
<void property="scores">
<array class="int" length="3">
<void index="0">
<int>100</int>
</void>
<void index="1">
<int>90</int>
</void>
<void index="2">
<int>75</int>
</void>
</array>
</void>
<void property="seat">
<object class="java.awt.Point">
<int>5</int>
<int>3</int>
</object>
</void>
</object>
</java>[b][b]
[/b][/b]
[/b]这个特定的 XML 文件未显示如何嵌入用于复位 bean 属性的方法调用,如添加侦听器以及将组件添加到容器。
读回
读取原始图的对象图就如保存它一样容易,但这次我们使用
清单 4. XML 的读回
[b]
// Read
XMLDecoder decoder = new XMLDecoder(
new BufferedInputStream(
new FileInputStream("Sample.xml")));
Sample sample2 = (Sample)decoder.readObject();
decoder.close();[/b]
完整的示例
从本质上来说,这个示例包括了将 JavaBean 组件状态编码进 XML 以及从 XML 中解码出来的全部内容。这个示例在后台进行的工作要比我们看到的多得多。但是,要使用类,您不必了解全部内容,就象进行序列化一样。如果您对自己生成 XML 文件感兴趣,您还必须阅读更多有关文件格式的内容。
这里是一个创建实例,对其进行编码,然后对其进行解码的完整的测试示例。
清单 5. 完整的测试示例
[b]
import net.zukowski.ibm.Sample;
import java.io.*;
import java.beans.*;
import java.awt.Point;
public class SampleTest {
public static void main (String args[]) throws Exception ...{
Sample sample = new Sample();
sample.setScores(new int[] ...{100, 90, 75});
sample.setName("Gore");
sample.setSeat(new Point(5, 3));
XMLEncoder encoder = new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream("Sample.xml")));
encoder.writeObject(sample);
encoder.close();
System.out.println(sample);
XMLDecoder decoder = new XMLDecoder(
new BufferedInputStream(
new FileInputStream("Sample.xml")));
Sample sample2 = (Sample)decoder.readObject();
decoder.close();
System.out.println(sample2);
}
}...[/b]
将 JavaBean 组件状态长期持久地保存在 XML 文档中的功能在 J2SE 的 1.4 版本中得到了实现。 Merlin 的魔力系列的这一部分向您展示如何使用新的
XMLEncoder和
XMLDecoder类,绕过序列化并且允许您生成完全初始化的 bean 实例。
Merlin 的这个功能可以将 JavaBean 组件状态长期持久地保存在 XML 文档中。序列化工作适合短期编组的需要(对于 CORBA 和 RMI)或适合将状态信息保存在一个执行的 servlet 中。但是序列化会产生许多问题,包括类库版本或 Java 运行时环境方面的问题。新的
XMLEncoder/
XMLDecoder类允许将 JavaBean 组件状态转储到文本文件中以便易于在 Java 程序外部进行修改,或者更有可能的是为了生成这种文件。让我们看一下如何使用这两个类以及如何分析生成的文件。
开始
开始时,我们需要定义一个我们要初始化、保存和重新创建的类。让我们定义一个带有以下 4 个属性的类:
测试分数的整数数组
只读
float属性,表示平均分数
String属性,代表学生的姓名
java.awt.Point属性,代表学生在班里的座位
这个可变的属性类型集将演示编码器如何处理不同的数据类型。
清单1
package net.zukowski.ibm;
import java.awt.Point;
public class Sample {
private int[] scores;
private String name;
private Point seat;
public void setScores(int[] value) ...{
scores = value;
}
public void setScores(int value, int position) ...{
scores[position] = value;
}
public int[] getScores() ...{
return scores;
}
public int getScores(int position) ...{
return scores[position];
}
public float getAverage() ...{
float sum = 0;
int count = scores.length;
float avg;
if (count == 0) ...{
avg = -1;
} else ...{
for (int i = 0; i < count; i++) ...{
sum += scores[i];
}
avg = sum / count;
}
return avg;
}
public void setName(String value) ...{
name = value;
}
public String getName() ...{
return name;
}
public void setSeat(Point value) ...{
seat = value;
}
public Point getSeat() ...{
return seat;
}
public String toString() ...{
return getClass().getName() +
"[scores=" + asString(scores) +
",avg=" + getAverage() +
",name=" + name +
",seat=" + seat + "]";
}
private String asString(int[] array) ...{
StringBuffer buffer = new StringBuffer("[");
for (int i=0, n=array.length; i < n; i++) ...{
if (i != 0) ...{
buffer.append(",");
}
buffer.append(array[i]);
}
buffer.append("]");
return buffer.toString();
}
}...
有一个有用的
toString()方法,我们可以使用这个方法直观地看到检索出的值是设置正确的。
保存状态
有了用于保存的类,我们可以创建一个实例并使用
XMLEncoder进行保存。这个类在
java.beans包中,它的工作原理与
ObjectOutputStream相同,但不是
OutputStream类层次结构的一部分。您可以将要保存到的输出流对象传入
OutputStream,并调用其
writeObject()方法将对象写入到流中。
[b]清单 2. 创建一个实例并将其保存为 XML[/b]
// Create
Sample sample = new Sample();
sample.setScores(new int[] {100, 90, 75});
sample.setName("Gore");
sample.setSeat(new Point(5, 3));
// Save
XMLEncoder encoder = new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream("Sample.xml")));
encoder.writeObject(sample);
encoder.close();...
!!!注意:XMLEncoder的writeObject(Object o)方法的参数(o)的类型类必须是public的,否则会报Class sun.reflect.misc.Trampoline can not access a member of class XXX.XXX.XXX with modifiers "什么什么"
检查格式
当检查清单 3 所示的 XML 文件时,您会注意到如何读取格式是与输出在一起编码的,在本例中是与 v1.4 beta 中的
XMLDecoder一起编码的。这种方法使得将来的发行版能够更改格式,这样如果使用的是比较旧的 XML 文件,新的解码器在生成 XML 文件时会知道使用的是哪种编码类型。从本质上来说,这个文件是一个正规 XML 文件,服从特定的 DTD(本文中没有引用到)。但是,解码器能够识别该文件。
[b]清单 3. 经过编码的 XML 样本实例[/b]
[b]
?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.0-beta" class="java.beans.XMLDecoder">
<object class="net.zukowski.ibm.Sample">
<void property="name">
<string>Gore</string>
</void>
<void property="scores">
<array class="int" length="3">
<void index="0">
<int>100</int>
</void>
<void index="1">
<int>90</int>
</void>
<void index="2">
<int>75</int>
</void>
</array>
</void>
<void property="seat">
<object class="java.awt.Point">
<int>5</int>
<int>3</int>
</object>
</void>
</object>
</java>[b][b]
[/b][/b]
[/b]这个特定的 XML 文件未显示如何嵌入用于复位 bean 属性的方法调用,如添加侦听器以及将组件添加到容器。
读回
读取原始图的对象图就如保存它一样容易,但这次我们使用
XMLDecoder。解码器的工作原理与
ObjectInputStream相同,使用它可将文件的
InputStream传送到构造函数中,并使用
readObject()方法读取对象。您仍然必须将结果强制转换为适当的类型。
清单 4. XML 的读回
[b]
// Read
XMLDecoder decoder = new XMLDecoder(
new BufferedInputStream(
new FileInputStream("Sample.xml")));
Sample sample2 = (Sample)decoder.readObject();
decoder.close();[/b]
完整的示例
从本质上来说,这个示例包括了将 JavaBean 组件状态编码进 XML 以及从 XML 中解码出来的全部内容。这个示例在后台进行的工作要比我们看到的多得多。但是,要使用类,您不必了解全部内容,就象进行序列化一样。如果您对自己生成 XML 文件感兴趣,您还必须阅读更多有关文件格式的内容。
这里是一个创建实例,对其进行编码,然后对其进行解码的完整的测试示例。
清单 5. 完整的测试示例
[b]
import net.zukowski.ibm.Sample;
import java.io.*;
import java.beans.*;
import java.awt.Point;
public class SampleTest {
public static void main (String args[]) throws Exception ...{
Sample sample = new Sample();
sample.setScores(new int[] ...{100, 90, 75});
sample.setName("Gore");
sample.setSeat(new Point(5, 3));
XMLEncoder encoder = new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream("Sample.xml")));
encoder.writeObject(sample);
encoder.close();
System.out.println(sample);
XMLDecoder decoder = new XMLDecoder(
new BufferedInputStream(
new FileInputStream("Sample.xml")));
Sample sample2 = (Sample)decoder.readObject();
decoder.close();
System.out.println(sample2);
}
}...[/b]
相关文章推荐
- XML与JAVABEAN序列化与反序列化的三方框架:Simple framework
- 【整理】Android中使用XML自定义组件各种状态下的背景图片
- 采用XSTREAM开源组件做xml的序列化和反序列化
- javaBean的XML序列化和Object序列化的比较,以及读写文件效率
- JavaBean-XML组件轻松实现JavaBeans到XML的相互转换
- [ServiceStack.Text] .net序列化,反序列化组件(号称最快,支持 JSON,XML,JSV格式)
- JavaBean-XML组件轻松实现JavaBeans到XML的相互转换
- JavaBean-XML组件轻松实现JavaBeans到XML的相互转换
- bean,javabean组件,序列化
- 序列化与JavaBean与xml互转
- Android中使用XML自定义组件各种状态下的背景图片
- JavaBean-XML组件轻松实现JavaBeans到XML的相互转换
- 采用数据库为Flex Tree组件的提供数据-XML数据生成
- 每天学一点flash(13) tree组件 与xml配合配合使用
- 文件上传功能的实现1(采用自编写的JavaBean组件)
- xml序列化的性能问题
- GstBin和sink组件的状态转换代码分析和相关逻辑
- List<T>到XML的序列化与反序列化
- xml不带命名空间的序列化
- XML序列化的简单例子