java castor_Castor功能与应用参考二

索引

2.1概述

1.示例需求

在运行下文中讲述的示例时,用户需要预先做一些准备工作。用户可以从castor网站上获取最新1.1.2.1版本包括castor-1.1.2.1.zip和castor-1.1.2.1-examples.zip解压到本地目录,在Eclipse中构建一个Java项目。然后将解压目录中的castor-1.1.2.1.jar,lib目录下的commons-logging-1.1.jar,log4j-1.2.13.jar和xerces-J_1.4.0.jar添加到项目的类路径中。

2.Castor XML映射概念

Castor XML 通过Mapping定义的方式简化了Java类和XML文档之间的绑定。尽管可以使用Castor默认的自省方式编组和解编Java对象,但是对于复杂的映射绑定,Mapping定义提供了更加细致的控制。同时,Mapping文件可以在一定程度上解耦合Java对象模型与XML文档,从而避免各自的变化给对方带来的影响。

2.1概述

Mpping文件本身也以XML文档格式定义。Mapping文档以Java对象模型为视角,用于描述Java对象如何映射为XML文档节点,Java对象中的字段属性如何映射为XML文档节点中的子节点或属性。

如上图所示,在Castor中,一个Java类映射为一个XML节点,Java类中的属性字段映射为XML节点下的子节点或者属性。描述上述映射的Mapping文件如下所示:

/p>

"http://castor.org/mapping.dtd">

Description of the mapping

2.2编组过程

在Castor中,一个Java类必须映射为一个XML节点。当Castor编组一个Java对象的过程如下:首先,如果存在映射信息,从映射信息中确定该对象所对应的XML节点名称;如果不存在映射信息,则使用对象的类名作为XML节点名。然后,使用映射文件中字段的映射信息确定Java对象中的一个字段属性如何转换为XML文档中的如下几种存在:

一个属性

一个节点

一个节点的文本

忽略(在映射文件中可以设定不编组某一字段属性,Castor将忽略该字段)

Castor遍历整个Java对象,如果发现一个Class类型的属性,则查找Mapping文件中的节点定义。

如果在Mapping文件中找不到一个类的对应信息,默认情况下,Castor会分析这个类的元数据,采用一组默认的规则来定义要编组的字段属性所映射的XML文档元素。默认规则如下:

所有原始数据类型,包括原始数据类型的对象封装类型(如Boolean,Short等)都编组为XML节点属性;

所有其他对象类型都编组为文本或者节点;

2.3解编过程

在解编过程中,当Castor查找到一个XML文档节点时,Castor首先查找映射信息来决定如何解编XML文档为Java对象。如果不存在映射信息,Castor会使用XML节点的名称决定如何构建类(Class)实例,例如,如果节点的名称为”test-element”,在Mapping文件不存在时,Castor将构建一个名称为”TestElement”的类。然后,Castor根据映射文件中关于字段属性的映射信息处理该XML文档节点下的内容。

3.映射文件定义详解

3.1Mapping文件的根节点

如上例XML Mapping文件所示,Mapping文件的根节点为。节点的Xml Schema定义为:

节点下的节点包括:

一个节点,可选的,用于添加描述信息

一个或多个节点,用于引用其他的映射文件

一个或多个节点,用于描述每一个定义Mapping的Java类

一个或多个节点,该节点在Castor JDO中使用,后续文档将详细解释

Mapping文件举例如下:

/p>

"http://castor.org/mapping.dtd">

Description of the mapping

.........

.........

3.2节点定义

节点的Schema定义如下:

节点包含了Java类与XML文档之间映射的所有信息。其中,详细描述了Java类中各个字段属性与XML文档元素的映射。

3.2.1节点的属性

Øname:映射的Java类名称,使用类的全名,如”com.acme.MyClass”。

Øextends:只有在该类扩展其他类时,使用该参数指定扩展的类。如果被扩展的类未在该Mapping文件中指定,则不能使用该属性。

Ødepends:在Castor JDO中指明类之间的依赖关系,用于表示数据库表中关联表的概念。

Øauto-complete:如果该属性值为”true”,则Castor在处理该类时首先采用自省的方式决定该类的字段属性,然后使用Mapping文件中对该字段属性的设定覆盖自省方式的操作。auto-complete属性可以让Castor的默认自省处理方式与Mapping定义方式很好的结合,从而降低对包含很多字段的类进行复杂的设定操作。

Øidentity:在Castor JDO中使用,用于描述该类实例的主键字段,详细信息参考Castor JDO部分。

Øaccess:在Castor JDO中使用,详细信息参考Castor JDO部分。

Økey-generator:在Castor JDO中使用,详细信息参考Castor JDO部分。

3.2.2节点的子节点

Ødescription:可选的属性,用于对该类添加描述性信息

Øcache-type:只在Castor JDO中使用,详细信息参考Castor JDO部分。

Ømap-to:可选属性,如果XML中节点名称与类(Class)名称不同,则使用该节点设定。默认的,Castor会自动分析XML节点名称和类名称之间的映射,如对于Java类”XxxYyy”,Castor会自动映射为XML节点”xxx-yyy”。如果用户不希望Castor自动生成该名称,则可以使用节点来指定XML映射名称。注意:仅用于XML文档中的根节点。

Øfield:节点下包含零个或多个节点。每个节点用于描述Java类中的一个字段属性。

映射举例

下面的例子将Java类MyClass映射为XML文档中的节点’’:

package mypackage

public class MyClass {

public int foo;

public String getBar() { ... }

public void setBar(String bar) { ... }

}

如果用户希望输出的XML文档格式如下:

...

则用户需要以如下方式设定Mapping映射文件:

...

...

3.3节点定义

节点的Schema定义如下:

节点用于指定给定Java类与XML文档节点的映射。节点只用于XML文档根节点,如果该节点未在Mapping文件中设定,则Castor采用如下处理策略:

Ø在编组过程中,通过Java类名称命名XML文档根节点名,如Java类”XxxYyy”映射为XML节点”xxx-yyy”

Ø在解编过程中,通过XML文档根节点名称确定Java类名称,如XML节点”test-element”映射为Java类”TestElement”

用户可以在castor.properties中指定Castor在Java类名称与XML文档节点名之间的转换策略。节点的属性包括:

Øxml:类映射的XML节点名称Java

Øns-uri:XML节点的名称空间URI

Øns-prefix:XML节点的名称空间前缀

Øelement-definition:True if the descriptor as created from a schema definition that was of type element (as opposed to a definition). This only is useful in the context of source code generation

Øldap-dn:在Castor XML中不使用该属性

Øldap-oc:在Castor XML中不使用该属性

3.4< field>节点定义

< field>节点的Schema定义如下:

节点用于描述如何编组/解编Java对象中的字段属性。Castor可以从节点描述中的”name”属性确定Java字段的名称;可以从节点描述中的”type”和”collection”属性确定Java字段的类型;可以从节点描述中的”direct”,”get-method”和”set-method”属性确定Java字段的访问方法。通过上述信息,Castor能够操作Java类中的字段属性。

Castor通过以下两个规则来判定某一字段的类型签名:

检查节点中的“类型”属性(”type”和”collection”)

如果节点中没有”collection”属性,”type”属性指定的类型即为该字段的Java类型。”type”属性值既可以是Java对象类型的全限定名(包含包名称),也可以是Castor定义的一系列简称。Castor支持的类型简称列表如下:

简称

原始类型

Java类型

other

N

java.lang.Object

string

N

java.lang.String

integer

Y

java.lang.Integer

long

Y

java.lang.Long

boolean

Y

java.lang.Boolean

double

Y

java.lang.Double

float

Y

java.lang.Float

big-decimal

N

java.math.BigDecimal

byte

Y

java.lang.byte.Type

date

N

java.util.Date

short

Y

java.lang.short.Type

char

Y

java.lang.Character.Type

bytes

N

bytes[]

chars

N

char[]

strings

N

string[]

loacle

N

java.util.Locale

Castor会自动将XML文档中的节点内容自动转换为上述Java对象类型。如果设定了”collection”属性,collection属性值遵从下面的对象对象列表:

简称

原始类型

Java类型

array

[]

[]

arraylist

java.util.List

java.util.Arraylist

vector

java.util.Vector

java.util.Vector

hashtable

java.util.Hashtable

java.util.Hashtable

collection

java.util.Collection

java.util.Arraylist

set

java.util.Set

java.util.Hashset

map

java.util.Map

java.util.Hashmap

sortedset

java.util.SortedSet

java.util.TreeSet

Collection集合中的对象为Java类型。对于Hashtable和Map类型的对象,Castor同时存储其键和值。对于其映射,可以使用org.exolab.castor.mapping.MapItem类通过顶层(相对于嵌套类映射)类映射定义和嵌套类映射定义来描述。

检查节点中的“签名”属性(”direct”,”set-method”和”get-method”)

如果”direct”属性设定为true,则在Java类定义中,该字段必须具有如下的声明:

public ;

如果”direct”属性设定为false或者该属性被忽略,Castor会通过该属性的存取方法访问该属性。首先,若设定了'get-method'或'set-method',Castor会访问如下方法签名:

public ();

public void ( value);

若没有设定'get-method'或'set-method'属性,Castor会尝试访问如下签名方法:

public get();

public void set( value);

是指Castor检查属性值,将其首字母转换为大写,其他字符保持不变。

collection字段属性处理的例外情况

在默认情况下,’get-method’属性返回集合字段实例,’set-method’属性设定集合字段实例。特例情况如下表所示:

'get-method'

If a 'get-method' is provided for a collection field, Castor - in adition to the default behaviour described above - will deviate from the standard case for the following special prefixes:

public Iterator iterate...();

A 'get-method' starting with the prefix 'iterate' is treated as Iterator method for the given collection field.

public Enumeration enum...();

A 'get-method' starting with 'enum' is treated as Enumeration method for the given collection field.

'set-method'

If 'set-method' is provided for a collection field, Castor - in addition to the default behaviour described above - will accept an 'add' prefix and expect the following signature:

public void add...( value);

This method is called for each collection element while unmarshalling.

3.4.1节点的属性

节点可以包含将Java字段映射为XML元素,数据库表列名称等信息。节点可配置的属性如下:

Øname:该属性是必须的,即使在该映射类中没有该字段属性。如果配置了”direct”属性,”name”属性值必须是映射对象中的一个public字段(该字段必须是public,非static和非transient的类型)。如果没有”direct”和”get-/set-method”属性设定,“name”属性值对应的字段通过该值确定其访问方法(采用Java Bean规范)。

Øtype:该字段属性的Java类型。Castor使用该信息将XML信息转换为Java对象信息(如将字符串转换为整型),定义该字段访问方法的签名。如果设定了”collection”属性,该属性信息用于指定集合中对象的类型信息。

Ørequired:在编组和解编过程中,该字段是否可选,默认值为false。

Øtransient:如果设定为”true”,该字段在处理过程中将被忽略。

Ødirect:如果为true,该字段在Java类定义中必须是public类型。

Øcollection:如果该字段存在多个,则Castor使用该属性的设定来处理他们。该类型用于定义对应Java类中集合的类型。

Øget-method:可选配置,”name”属性对应Java类字段的访问方法,具体使用参考前文描述。

Øset-method:可选配置,”name”属性对应Java类字段的访问方法,具体使用参考前文描述。

Øcreate-method:工厂方法,用于构建FieldHandler实例。

3.4.2节点的子节点

在XML Mapping中,节点的子节点仅包含一个节点,用于描述如何将该字段属性映射到XML文档元素。

Castor自0.9.5版本以后,支持将一个节点映射为该字段所属Java类构造函数的参数,这种机制通过”set-method”属性来实现。如果需要设定一个字段作为该类对象初始化时构造函数的一个参数,可以设定该字段在Mapping文件中节点的”set-method”属性为”1%”-“9%”。 ”1%”表示构造函数的第一个参数,依次类推。这种机制举例如下:

假定存在如下所示的Java类Foo,Foo类除了具有一个默认的构造函数外,还有一个具有参数的构造函数。

public class Foo {

private int size = 20;

public Foo() { }

public Foo(int size) {

this.size = size;

}

public int getSize() {

return size;

}

public void setSize(int size) {

this.size = size;

}

}

如果用户希望在实例化Foo类时,调用Foo类具有参数的构造函数而不是默认无参构造函数,则通过设定如下的映射文件实现。

Mapping文件中的setMethod=”1%”的设定,会告诉Castor在实例化Foo类时,使用size属性字段作为构造Foo(int)的参数。

注意:如果设定了”set-method”属性,则”get-method”属性也必须设定。

3.5节点定义

节点的用于描述Java字段如何在XML文档中映射展现。在编组和解编过程中均要使用。

节点的Schema定义如下:

3.5.1节点的属性

Øname:XML节点或属性的名称。注意:该属性值必须是QName,可以使用名称空间前缀来表明该节点或属性所属的特定名称空间,该前缀在编组过程中并不保留或使用,只是用来保持文档的格式良好。

Øauto-naming:如果未设定name属性,auto-naming属性用于提示是否Castor自动为该字段构建相应的名称。通常情况下,使用节点中的name属性值作为XML元素的名称。

Øtype: 该节点在XML文档中的 Schema类型,Castor编组框架使用该属性确定对XML节点的处理方式。如”QName”。

Ølocation:允许用户设定XML文档中 “间接路经”上的节点作为该Java字段属性的映射(如该字段所属类的XML节点映射为“AAA”,该节点的名称为“TTT”,但不是“AAA节点的子节点”,而是“AAA”节点的子节点“BBB”节点的子节点,则可以使用location属性映射为XML文档中的“AAA/BBB/TTT”。详细信息参看下述“Loaction属性简介”。

ØQName-prefix:如果该字段对应XML文档节点中的一个QName值,则可以使用该属性设定其前缀。详细信息参考“Castor源代码自动生成章节”。

Øreference:在解编该字段时,指明该字段是否看作一个对象引用。

Ømatches:允许覆盖节点名称的匹配规则。该属性值是一个标准的正则表达式,用于替代”name”属性。如果值为”*”,则可以匹配任何XML节点名称,但是仅当不存在其他字段与XML节点名称匹配时,使用该匹配。

Ønode:表明该字段映射成为XML文档中的属性,节点还是文本元素。默认情况下,原始类型的字段映射成XML属性,其他的映射成为XML节点。

Øtransient:如果其值设定为true,则视该节点为临时的,不做处理。默认继承节点中transient属性值。

3.5.2中使用嵌套的类映射

Castor自0.9.5.3版本开始,节点支持嵌套的类映射定义。该功能在某个类映射信息需要在多个地方指定时非常方便,如映射Hashtable/HashMap/Map等集合类时的情况。具体使用参考下面的例子:

嵌套类举例

3.5.3location属性简介

节点中的location属性允许用户将字段映射为XML文档中的内嵌节点或者在映射节点封装一个节点。封装节点只出现在XML文档结构中,与Mapping文件定义的Java对象没有直接映射关系。下面仍以Foo类为例,

public class Foo {

private Bar bar = null;

public Foo();

public getBar() {

return bar;

}

public void setBar(Bar bar) {

this.bar = bar;

}

}

我们希望将该类映射成为下面所示的XML文档(注:’abc’节点并不存在于Foo或者Bar类的定义中)

;

...

为实现上述映射,我们以如下方式定义Mapping文件

...

...

需要注意的是,“location”属性的值指定的是封装的节点的名称,如果希望封装多层节点,则节点名称之间使用”/”分隔,如下例所示:

此外,用户还需要注意的是,节点中的属性”name”指定的xml元素名称并不是“location”属性中指定的封装节点的一部分。同时,封装节点的父节点总是其所封装字段所在类对象映射的节点。“location”属性同样可以封装XML属性元素,如下所示的映射定义:

生成的XML文档为:

;

4.映射文件使用举例

下面我们以一个完整的例子,说明如何使用Castor的Mapping映射文件实现Java类与XML文档之间的相互转换。

首先,我们定义一个名为”order.xml”的数据文件,我们用这个XML文件描述一个订单,该订单中包含这个订单的客户信息,以及客户在此订单中所订购的货物。一个订单中可以存在多个货物。

order.xml

Jean Smith

2000, Alameda de las Pulgas, San Mateo, CA 94403

Stuffed Penguin

10

8.95

Chocolate

5

28.50

Cookie

30

0.85

我们要为该订单定义三个Java类,分别描述该订单,订单的客户和货物。

ØMyOrder:代表该订单

ØClientData:代表订单的客户

ØItem:代表订单中的一项货物

这三个Java类的代码如下所示:

MyOrder.java

importjava.util.Vector;

importjava.util.Enumeration;

publicclassMyOrder {

privateString_ref;

privateClientData _client;

privateVector_items;

privatefloat_total;

publicvoidsetReference(String ref) {

_ref= ref;

}

publicString getReference() {

return_ref;

}

publicvoidsetClientData(ClientData client) {

_client = client;

}

publicClientData getClientData() {

return_client;

}

publicvoidsetItemsList(Vector items) {

_items= items;

}

publicVector getItemsList() {

return_items;

}

publicvoidsetTotal(floattotal) {

_total= total;

}

publicfloatgetTotal() {

return_total;

}

// Do some processing on the data

publicfloatgetTotalPrice() {

floattotal = 0.0f;

for(Enumeration e =_items.elements(); e.hasMoreElements();) {

Item item = (Item) e.nextElement();

total += item._quantity * item._unitPrice;

}

returntotal;

}

}

ClientData.java

publicclassClientData {

privateString_name;

privateString_address;

publicvoidsetName(String name) {

_name= name;

}

publicString getName() {

return_name;

}

publicvoidsetAddress(String address) {

_address= address;

}

publicString getAddress() {

return_address;

}

}

Item.java

publicclassItem {

publicString_reference;

publicint_quantity;

publicfloat_unitPrice;

publicString_description;

}

现在,我们有了预期的XML文档定义,也有了描述文档的Java类定义。下一步,我们定义XML文档与Java类之间的映射。在下面的mapping.xml文件中,我们定义了三个类MyOrder、ClientData和Item的映射。

mapping.xml

/p>

"http://castor.org/mapping.dtd">

具备上述资源后,我们通过下面的Java代码测试Castor通过Mapping映射文件来实现XML文档与Java对象间的相互转换。

main.java

importorg.exolab.castor.mapping.Mapping;

importorg.exolab.castor.xml.Unmarshaller;

importorg.exolab.castor.xml.Marshaller;

importjava.io.FileReader;

importjava.io.OutputStreamWriter;

importorg.xml.sax.InputSource;

publicclassMain {

publicstaticvoidmain(String args[]) {

Mapping mapping =newMapping();

try{

// 1.从Mapping.xml文件中加载映射信息

mapping.loadMapping("mapping.xml");

// 2.解编order.xml文档,构造java对象

Unmarshaller unmar =newUnmarshaller(mapping);

MyOrder order = (MyOrder) unmar.unmarshal(newInputSource(

newFileReader("order.xml")));

// 3.调用Java类MyOrder的对象实例方法,修改该对象实例

floattotal = order.getTotalPrice();

System.out.println("Order total price = "+ total);

order.setTotal(total);

// 4.将修改后的对象实例重新编组为XML文档并输出到控制台

Marshaller marshaller =newMarshaller(newOutputStreamWriter(

System.out));

marshaller.setMapping(mapping);

marshaller.marshal(order);

}catch(Exception e) {

System.out.println(e);

return;

}

}

}

用户可以比较原来的order.xml文档与输出到控制台的XML文档数据的差别,从而体会Castor XML编组框架的功能。

posted on 2007-11-28 11:42 IT扁担 阅读(2636) 评论(0)  编辑  收藏 所属分类: 开源框架

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值