﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-菜鸟已逝-文章分类-框架相关</title><link>http://www.blogjava.net/lcwlv929/category/26052.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 23 Sep 2007 15:44:38 GMT</lastBuildDate><pubDate>Sun, 23 Sep 2007 15:44:38 GMT</pubDate><ttl>60</ttl><item><title>Portal Framework介绍</title><link>http://www.blogjava.net/lcwlv929/articles/147079.html</link><dc:creator>炜</dc:creator><author>炜</author><pubDate>Fri, 21 Sep 2007 05:23:00 GMT</pubDate><guid>http://www.blogjava.net/lcwlv929/articles/147079.html</guid><wfw:comment>http://www.blogjava.net/lcwlv929/comments/147079.html</wfw:comment><comments>http://www.blogjava.net/lcwlv929/articles/147079.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcwlv929/comments/commentRss/147079.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcwlv929/services/trackbacks/147079.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1 概述2 基本概念2.1 Portal定义2.2 Portlet定义2.3 Portal页面的元素2.4 Portlet生命周期2.5 Portlet标签库2.6 JSR168和WSRP3 Portal的功能4 部分开源Portal框架的分析和比较4.1 评价标准4.2 选中的开源Portal框架4.3 评价结果1概述&nbsp;&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/lcwlv929/articles/147079.html'>阅读全文</a><img src ="http://www.blogjava.net/lcwlv929/aggbug/147079.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcwlv929/" target="_blank">炜</a> 2007-09-21 13:23 <a href="http://www.blogjava.net/lcwlv929/articles/147079.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML 与 Java 技术: 用 Castor 进行数据绑定</title><link>http://www.blogjava.net/lcwlv929/articles/145063.html</link><dc:creator>炜</dc:creator><author>炜</author><pubDate>Fri, 14 Sep 2007 02:29:00 GMT</pubDate><guid>http://www.blogjava.net/lcwlv929/articles/145063.html</guid><wfw:comment>http://www.blogjava.net/lcwlv929/comments/145063.html</wfw:comment><comments>http://www.blogjava.net/lcwlv929/articles/145063.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcwlv929/comments/commentRss/145063.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcwlv929/services/trackbacks/145063.html</trackback:ping><description><![CDATA[<blockquote>对于主要关心文档数据内容的应用程序，Java XML 数据绑定是一种代替 XML 文档模型的强大机制。本文中，企业 Java 专家 Dennis Sosnoski 介绍数据绑定，并讨论什么使它如此令人瞩目。然后，他向读者展示了如何利用 Java 数据绑定的开放源代码 Castor 框架来处理日益复杂的文档。如果您的应用程序更多的把 XML 作为数据而不是文档，您就会愿意了解这种处理 XML 和 Java 技术的简单有效的方法。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p>应用程序中使用 XML 文档的多数方法都把重点放在 XML 上：从 XML 的观点使用文档，按照 XML 元素、属性和字符数据内容编程。如果应用程序主要关心文档的 XML 结构，那么这种方法非常好。对于更关心文档中所含数据而非文档本身的许多应用程序而言， <em>数据绑定</em>提供了一种更简单的使用 XML 的方法。 </p>
<p><a name="h1"><span class="atitle">文档模型与数据绑定</span></a></p>
<p>本系列文章的上一篇（请参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources">参考资料</a>）所讨论的文档模型，是与数据绑定最接近的替代方案。文档模型和数据绑定都在内存中建立文档的表示，都需要在内部表示和标准文本 XML 之间双向转换。两者的区别在于文档模型尽可能保持 XML 结构，而数据绑定只关心应用程序所使用的文档数据。 </p>
<p>为了说明这一点，图 1 给出了一个简单 XML 文档的数据模型视图。文档成分——在这个例子中只有元素和文本节点——通过反映原始 XML 文档的结构连接在一起。形成的节点树很容易和原始文档联系，但要解释树中表示的实际数据就不那么容易了。</p>
<br />
<a name="figure1"><strong>图 1. 文档的文档模型视图</strong></a><br />
<img height="220" alt="文档的文档模型视图" src="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/document-model.gif" width="600" /> <br />
<p>如果应用程序使用 XML 文档模型方法，您就需要处理这种类型的树。这种情况下，您将使用节点之间的父子关系在树的上下层之间导航，使用属于同一父节点的子女之间的兄弟关系在树的同一层中导航。您可以非常详尽地处理树结构，当把树序列化为文本时，生成的 XML 文档将反映您所做的修改（比如插入的注释）。</p>
<p>现在来看看与图 1 截然不同的图 2，它表示同一文档的数据绑定视图。在这里，转换过程几乎隐藏了原始 XML 文档的所有结构，但是因为只有通过两个对象，更容易看清楚真正的数据，也更很容易访问这些数据。</p>
<br />
<a name="figure2"><strong>图 2. 文档的数据绑定视图</strong></a><br />
<img height="220" alt="文档的数据绑定视图" src="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/data-binding.gif" width="566" /> <br />
<p>使用这种数据结构就像是一般的 Java 编程——甚至根本不需要知道 XML！（哦，还是不要走得 <em>太</em>远了——我们这些专家顾问还得活&#8230;&#8230;）您的项目中至少要有人明白，这种数据结构和 XML 文档之间的映射是如何建立的，但这仍然是向简化迈出的一大步。 </p>
<p>不 <em>仅仅</em>是编程的简化，数据绑定还带来其他的好处。与文档模型方法相比，因为抽掉了许多文档细节，数据绑定通常需要的内存更少。比如前面两个图中所示的数据结构：文档模型方法使用了 10 个单独的对象，与此相比数据绑定只使用了两个。要创建的东西少，构造文档的数据绑定表示可能就更快一些。最后，数据绑定与文档模型相比，应用程序可以更快地访问数据，因为您可以控制如何表示和存储数据。我后面还要讲到这一点。 </p>
<p>既然数据绑定那么好，为何还要使用文档模型呢？以下两种情况需要使用文档模型：</p>
<ul>
    <li>应用程序真正关注文档结构的细节。比方说，如果您在编写一个 XML 文档编辑器，您就会坚持使用文档模型而非数据绑定。
    <li>您处理的文档没有固定的结构。比如实现一种通用的 XML 文档数据库，数据绑定就不是一种好办法。 </li>
</ul>
<p>许多应用程序使用 XML 传输数据，但并不关心文档表示的细节。这类应用程序非常适合使用数据绑定。如果您的应用程序符合这种模式，请继续读下去。</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="h2"><span class="atitle">Castor 框架</span></a></p>
<p>目前有几种不同的框架支持 Java XML 数据绑定，但还没有标准的接口。这种情况最终会得到改变：Java Community Process (JCP) 的 JSR-031 正在努力定义这方面的标准（请参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources">参考资料</a>）。现在让我们选择一个框架并学习使用它的接口。 </p>
<p>本文选择了 Castor 数据绑定框架。Castor 项目采用 BSD 类型的证书，因此可在任何类型的应用程序（包括完整版权的项目）中使用。 Castor 实际上仅仅有 XML 数据绑定，它还支持 SQL 和 LDAP 绑定，尽管本文中不讨论这些其他的特性。该项目从 2000 年初开始发起，目前处于后 beta 状态（一般可以使用这个版本，但是如果需要问题修正，您可能需要升级到目前的 CVS 版本）。请参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources">参考资料</a>部分的 Castor 站点链接，以了解更多的细节并下载该软件。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="h3"><span class="atitle">默认绑定</span></a></p>
<p>Castor XML 数据绑定很容易上手，甚至不需要定义 XML 文档格式。只要您的数据用类 JavaBean 的对象表示，Castor 就能自动生成表示这些数据的文档格式，然后从文档重构原始数据。</p>
<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee"><a name="N100BF"><strong>数据绑定词汇表</strong></a><br />
                        <p>下面这个小小的词汇表列出了本文中要用到的一些术语：</p>
                        <p><em>编组</em>是在内存中生成对象的 XML 表示的过程。与 Java 序列化一样，这种表示需要包括所有依赖的对象：主对象引用的对象、这些对象引用的其他对象、等等。 </p>
                        <p><em>解组</em>是上述过程的逆过程，在内存中从 XML 表示创建对象（以及依赖的对象）。 </p>
                        <p><em>映射</em>是用于编组和解组的一些规则。Castor 有一些内建的规则定义了默认映射，本文这一部分将要描述。它也允许您使用单独的映射文件，参见后述。 </p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>那么&#8220;类 JavaBean&#8221;是什么意思呢？真正的 JavaBean 是可视化组件，可以在开发环境中配置以用于 GUI 布局。一些源于真正 JavaBean 的惯例已经被 Java 团体普遍接受，特别是对于数据类。如果一个类符合以下惯例，我就称之为是&#8220;类 JavaBean&#8221;的： </p>
<ul>
    <li>这个类是公共的
    <li>定义了公共的默认（没有参数）构造函数
    <li>定义了公共的 <code>getX</code> 和 <code>setX</code> 方法访问属性（数据）值 </li>
</ul>
<p>关于技术定义已经扯得太远了，当提到这些类 JavaBean 类时，我将不再重复说明，只是称之为&#8220;bean&#8221;类。</p>
<p>在整篇文章中，我将使用航线班机时刻表作为示例代码。我们从一个简单的 bean 类开始说明它的工作原理，这个类表示一个特定的航班，包括四个信息项：</p>
<ul>
    <li>飞机编号（航空公司）
    <li>航班编号
    <li>起飞时间
    <li>抵达时间 </li>
</ul>
<p>下面的清单 1 给出了处理航班信息的代码。</p>
<br />
<a name="code1"><strong>清单 1. 航班信息 bean</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class FlightBean
            {
            private String m_carrier;
            private int m_number;
            private String m_departure;
            private String m_arrival;
            public FlightBean() {}
            public void setCarrier(String carrier) {
            m_carrier = carrier;
            }
            public String getCarrier() {
            return m_carrier;
            }
            public void setNumber(int number) {
            m_number = number;
            }
            public int getNumber() {
            return m_number;
            }
            public void setDepartureTime(String time) {
            m_departure = time;
            }
            public String getDepartureTime() {
            return m_departure;
            }
            public void setArrivalTime(String time) {
            m_arrival = time;
            }
            public String getArrivalTime() {
            return m_arrival;
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>您可以看到，这个 bean 本身没有什么意思，因此我想增加一个类并在默认的 XML 绑定中使用它，如清单 2 所示。</p>
<br />
<a name="code2"><strong>清单 2. 测试默认的数据绑定</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">import java.io.*;
            import org.exolab.castor.xml.*;
            public class Test
            {
            public static void main(String[] argv) {
            // build a test bean
            FlightBean bean = new FlightBean();
            bean.setCarrier("AR");
            bean.setNumber(426);
            bean.setDepartureTime("6:23a");
            bean.setArrivalTime("8:42a");
            try {
            // write it out as XML
            File file = new File("test.xml");
            Writer writer = new FileWriter(file);
            Marshaller.marshal(bean, writer);
            // now restore the value and list what we get
            Reader reader = new FileReader(file);
            FlightBean read = (FlightBean)
            Unmarshaller.unmarshal(FlightBean.class, reader);
            System.out.println("Flight " + read.getCarrier() +
            read.getNumber() + " departing at " +
            read.getDepartureTime() +
            " and arriving at " + read.getArrivalTime());
            } catch (IOException ex) {
            ex.printStackTrace(System.err);
            } catch (MarshalException ex) {
            ex.printStackTrace(System.err);
            } catch (ValidationException ex) {
            ex.printStackTrace(System.err);
            }
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee"><a name="N10123"><strong>Castor 不仅能用于 bean</strong></a><br />
                        <p>实际上，Castor 不仅仅能用于本文所述的类 JavaBean 类。它也可以访问带有公共成员变量的简单数据对象类的数据。比如，稍微改动前述的 <code>Test</code> 类，您就可以对航班数据使用如下的定义，并最终得到同样的 XML 格式： </p>
                        <table cellspacing="0" cellpadding="0" width="100%" border="0">
                            <tbody>
                                <tr>
                                    <td class="code-outline">
                                    <pre class="displaycode">public class FlightData
                                    {
                                    public String carrier;
                                    public int number;
                                    public String departure;
                                    public String arrival;
                                    }</pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <br />
                        <p>为了使 Castor 正常工作，一个类必须全部采用这种方式或那种方式。如果类定义了 <em>任何</em> <code>getX</code> 或 <code>setX</code> 方法，Castor 就将其视作 bean，并在编组和解组时只使用这些方法。 </p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>这段代码首先构造了一个 <code>FlightBean</code> bean，并使用一些固定的数据初始化它。然后用该 bean 默认的 Castor XML 映射将其写入一个输出文件。最后又读回生成的 XML， 同样使用默认映射重构 bean，然后打印重构的 bean 中的信息。结果如下： </p>
<p><code>Flight AR426 departing at 6:23a and arriving at 8:42a</code> </p>
<p>这个输出结果表明您已经成功地来回转换了航班信息（不算太糟，只有两次方法调用）。现在我还不满足于简单控制台输出，准备再往深处挖一挖。</p>
<p><a name="h4"><span class="smalltitle">幕后</span></a></p>
<p>为了更清楚地了解这个例子中发生了什么，看一看 <code>Marshaller.marshal()</code> 调用生成的 XML。文档如下： </p>
<table cellspacing="0" cellpadding="0" width="65%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;?xml version="1.0"?&gt;
            &lt;flight-bean number="426"&gt;
            &lt;arrival-time&gt;8:42a&lt;/arrival-time&gt;
            &lt;departure-time&gt;6:23a&lt;/departure-time&gt;
            &lt;carrier&gt;AR&lt;/carrier&gt;
            &lt;/flight-bean&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>Castor 使用 Java 内部检查机制检查 <code>Marshaller.marshal()</code> 调用传递的对象。在本例中，它发现了定义的四个属性值。Castor 在输出的 XML 中创建一个元素（文档的根元素）表示整个对象。元素名从对象的类名中衍生出来，在这里是 <code>flight-bean</code> 。然后Castor 用以下两种方法中的一个，把该对象的属性值包括进来： </p>
<ul>
    <li>对于具有基本类型值的属性创建元素的一个属性（本例中只有 <code>number</code> 属性通过 <code>getNumber()</code> 方法公开为 <code>int</code> 值）。
    <li>对于每个具有对象类型值的属性创建根元素的一个子元素（本例中的所有其他属性，因为它们是字符串）。 </li>
</ul>
<p>&nbsp;</p>
<p>结果就是上面所示的 XML 文档。</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="h5"><span class="atitle">改变 XML 格式</span></a></p>
<p>如果不喜欢 Castor 的默认映射格式，您可以方便地改变映射。在我们的航班信息例子中，比方说，假定我们需要更紧凑的数据表示。使用属性代替子元素有助于实现这个目标，我们也许还希望使用比默认的名字更短一些的名字。如下所示的文档就可以很好地满足我们的需要：</p>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;?xml version="1.0"?&gt;
            &lt;flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><a name="h6"><span class="smalltitle">定义映射</span></a></p>
<p>为了让 Castor 使用这种格式而非默认的格式，首先需要定义描述这种格式的映射。映射描述本身（非常意外的）是一个 XML 文档。清单 3 给出了把 bean 编组成上述格式的映射。</p>
<br />
<a name="code3"><strong>清单 3. 紧凑格式的映射</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;!DOCTYPE databases PUBLIC
            "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
            "http://castor.exolab.org/mapping.dtd"&gt;
            &lt;mapping&gt;
            &lt;description&gt;Basic mapping example&lt;/description&gt;
            &lt;class name="FlightBean" auto-complete="true"&gt;
            &lt;map-to xml="flight"/&gt;
            &lt;field name="carrier"&gt;
            &lt;bind-xml name="carrier" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;field name="departureTime"&gt;
            &lt;bind-xml name="depart" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;field name="arrivalTime"&gt;
            &lt;bind-xml name="arrive" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;/class&gt;
            &lt;/mapping&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><code>class</code> 元素定义了一个命名类 <code>FlightBean</code> 的映射。通过在该元素中加入 <code>auto-complete</code> 属性并把值设为 <code>true</code> ，您可以告诉 Castor 对于该类的任何属性，只要没有在这个元素中专门列出，就使用默认映射。这样非常简便，因为 <code>number</code> 属性已经按照希望的方式处理了。 </p>
<p>子元素 <code>map-to</code> 告诉 Castor，要把 <code>FlightBean</code> 类的实例映射为 XML 文档中的 <code>flight</code> 元素。如果您继续使用默认的元素名 <code>flight-bean</code> （参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#h4">幕后</a>小节中默认映射输出的例子），可以不使用该元素。 </p>
<p>最后，对于每个希望以非默认方式处理的属性，可以引入一个 <code>field</code> 子元素。这些子元素都按照相同的模式： <code>name</code> 属性给出映射的属性名， <code>bind-xml</code> 子元素告诉 Castor 如何映射那个属性。这里要求把每个属性映射成给定名称的属性。 </p>
<p><a name="h7"><span class="smalltitle">使用映射</span></a></p>
<p>现在已经定义了一个映射，您需要告诉 Castor 框架在编组和解组数据时使用那个映射。清单 4 说明了要实现这一点，需要对前面的代码做哪些修改。</p>
<br />
<a name="code4"><strong>清单 4. 使用映射编组和解组</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">...
            // write it out as XML (if not already present)
            Mapping map = new Mapping();
            map.loadMapping("mapping.xml");
            File file = new File("test.xml");
            Writer writer = new FileWriter(file);
            Marshaller marshaller = new Marshaller(writer);
            marshaller.setMapping(map);
            marshaller.marshal(bean);
            // now restore the value and list what we get
            Reader reader = new FileReader(file);
            Unmarshaller unmarshaller = new Unmarshaller(map);
            FlightBean read = (FlightBean)unmarshaller.unmarshal(reader);
            ...
            } catch (MappingException ex) {
            ex.printStackTrace(System.err);
            ...
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>与前面 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code2">清单 2</a>默认映射所用的代码相比，这段代码稍微复杂一点。在执行任何其他操作之前，首先要创建一个 <code>Mapping</code> 对象载入您的映射定义。真正的编组和解组也有区别。为了使用这个映射，您需要创建 <code>Marshaller</code> 和 <code>Unmarshaller</code> 对象，用定义的映射配置它们，调用这些对象的方法，而不是像第一个例子那样使用静态方法。最后，您必须提供对映射错误产生的另一个异常类型的处理。 </p>
<p>完成这些修改后，您可以尝试再次运行程序。控制台输出与第一个例子相同（如 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code2">清单 2</a>所示），但是现在的 XML 文档看起来符合我们的需要： </p>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;?xml version="1.0"?&gt;
            &lt;flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="h8"><span class="atitle">处理集合</span></a></p>
<p>现在单个航班数据已经有了我们喜欢的形式，您可以定义一个更高级的结构：航线数据。这个结构包括起降机场的标识符以及在该航线上飞行的一组航班。清单 5 给出了一个包含这些信息的 bean 类的例子。</p>
<br />
<a name="code5"><strong>清单 5. 航线信息 bean</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">import java.util.ArrayList;
            public class RouteBean
            {
            private String m_from;
            private String m_to;
            private ArrayList m_flights;
            public RouteBean() {
            m_flights = new ArrayList();
            }
            public void setFrom(String from) {
            m_from = from;
            }
            public String getFrom() {
            return m_from;
            }
            public void setTo(String to) {
            m_to = to;
            }
            public String getTo() {
            return m_to;
            }
            public ArrayList getFlights() {
            return m_flights;
            }
            public void addFlight(FlightBean flight) {
            m_flights.add(flight);
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在这段代码中，我定义了一个 <code>addFlight()</code> 方法，用于每次增加一个属于这条航线的航班。这是在测试程序中建立这种数据结构非常简便的办法，但是可能和您预料的相反， Castor 在解组时并不使用种方法向航线中增加航班。相反，它使用 <code>getFlights()</code> 方法访问一组航班，然后直接添加到集合中。 </p>
<p>在映射中处理航班集合只需要稍微改变上一个例子（如 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code3">清单 3</a>所示）中的 <code>field</code> 元素。清单 6 显示了修改后的映射文件。 </p>
<br />
<a name="code6"><strong>清单 6. 映射包含一组航班的航线</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;!DOCTYPE databases PUBLIC
            "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
            "http://castor.exolab.org/mapping.dtd"&gt;
            &lt;mapping&gt;
            &lt;description&gt;Collection mapping example&lt;/description&gt;
            &lt;class name="RouteBean"&gt;
            &lt;map-to xml="route"/&gt;
            &lt;field name="from"&gt;
            &lt;bind-xml name="from" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;field name="to"&gt;
            &lt;bind-xml name="to" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;field name="flights" collection="collection" type="FlightBean"&gt;
            &lt;bind-xml name="flight"/&gt;
            &lt;/field&gt;
            &lt;/class&gt;
            &lt;class name="FlightBean" auto-complete="true"&gt;
            &lt;field name="carrier"&gt;
            &lt;bind-xml name="carrier" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;field name="departureTime"&gt;
            &lt;bind-xml name="depart" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;field name="arrivalTime"&gt;
            &lt;bind-xml name="arrive" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;/class&gt;
            &lt;/mapping&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>一切都和上一个映射（如 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code3">清单 3</a>所示）完全相同，只不过用 <code>field</code> 元素定义了一个 <code>RouteBean</code> 的 <code>flights</code> 属性。这个映射用到了两个原来不需要的属性。 <code>collection</code> 属性的值 <code>collection</code> 把该属性定义成一个 java.util.Collection （其他值分别定义数组，java.util.Vectors 等等）。 <code>type</code> 属性定义包含在集合中的对象类型，值是完整的限定类名。这里的值是 <code>FlightBean</code> ，因为对这些类我没有使用包。 </p>
<p>另一个区别在 <code>FlightBean</code> 类元素中，不再需要使用 <code>map-to</code> 子元素定义绑定的元素名。定义 <code>RouteBean</code> 的 <code>flights</code> 属性的 <code>field</code> 元素，通过它的 <code>bind-xml</code> 子元素定义了这一点。因为编组或解组 <code>FlightBean</code> 对象只能通过该属性，它们将永远使用这个 <code>bind-xml</code> 元素设定的名称。 </p>
<p>我不再详细列出这个例子的测试程序，因为数据绑定部分和上一个例子相同。以下是用一些示例数据生成的 XML 文档：</p>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;?xml version="1.0"?&gt;
            &lt;route from="SEA" to="LAX"&gt;
            &lt;flight carrier="AR" depart="6:23a" arrive="8:42a"
            number="426"/&gt;
            &lt;flight carrier="CA" depart="8:10a" arrive="10:52a"
            number="833"/&gt;
            &lt;flight carrier="AR" depart="9:00a" arrive="11:36a"
            number="433"/&gt;
            &lt;/route&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="h9"><span class="atitle">对象引用</span></a></p>
<p>现在可以为处理完整的航班时刻表做最后的准备了。您还需要增加三个 bean： </p>
<ul>
    <li><code>AirportBean</code> 用于用于机场信息
    <li><code>CarrierBean</code> 用于航线信息
    <li><code>TimeTableBean</code> 把一切组合起来 </li>
</ul>
<p>为了保持趣味性，除了上一个例子（参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#h8">处理集合</a>）中用到的 <code>RouteBean</code> 和 <code>FlightBean</code> 之间的从属关系，您还要在 bean 之间增加一些联系。 </p>
<p><a name="h10"><span class="smalltitle">连接 bean</span></a></p>
<p>要增加的第一个联系是修改 <code>FlightBean</code> ，让它直接引用班机信息，而不再仅仅用代码标识班机。以下是对 <code>FlightBean</code> 的修改： </p>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class FlightBean
            {
            private CarrierBean m_carrier;
            ...
            public void setCarrier(CarrierBean carrier) {
            m_carrier = carrier;
            }
            public CarrierBean getCarrier() {
            return m_carrier;
            }
            ...
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>然后对 <code>RouteBean</code> 做同样的修改，让它引用机场信息： </p>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class RouteBean
            {
            private AirportBean m_from;
            private AirportBean m_to;
            ...
            public void setFrom(AirportBean from) {
            m_from = from;
            }
            public AirportBean getFrom() {
            return m_from;
            }
            public void setTo(AirportBean to) {
            m_to = to;
            }
            public AirportBean getTo() {
            return m_to;
            }
            ...
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>我没有给出新增 bean 自身的代码，因为和前面的代码相比没有什么新鲜的东西。您可以从下载文件 code.jar 中找到完整的示例代码（请参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources">参考资料</a>）。 </p>
<p><a name="h11"><span class="smalltitle">映射引用</span></a></p>
<p>您可能需要映射文档的其他一些特性，以支持编组和解组的对象之间的引用。清单 7 给出了一个完整的映射：</p>
<br />
<a name="code7"><strong>清单 7. 完整的时刻表映射</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;!DOCTYPE databases PUBLIC
            "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
            "http://castor.exolab.org/mapping.dtd"&gt;
            &lt;mapping&gt;
            &lt;description&gt;Reference mapping example&lt;/description&gt;
            &lt;class name="TimeTableBean"&gt;
            &lt;map-to xml="timetable"/&gt;
            &lt;field name="carriers" type="CarrierBean" collection="collection"&gt;
            &lt;bind-xml name="carrier"/&gt;
            &lt;/field&gt;
            &lt;field name="airports" type="AirportBean" collection="collection"&gt;
            &lt;bind-xml name="airport"/&gt;
            &lt;/field&gt;
            &lt;field name="routes" type="RouteBean" collection="collection"&gt;
            &lt;bind-xml name="route"/&gt;
            &lt;/field&gt;
            &lt;/class&gt;
            &lt;class name="CarrierBean" identity="ident" auto-complete="true"&gt;
            &lt;field name="ident"&gt;
            &lt;bind-xml name="ident" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;/class&gt;
            &lt;class name="AirportBean" identity="ident" auto-complete="true"&gt;
            &lt;field name="ident"&gt;
            &lt;bind-xml name="ident" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;/class&gt;
            &lt;class name="RouteBean"&gt;
            &lt;field name="from" type="AirportBean"&gt;
            &lt;bind-xml name="from" node="attribute" reference="true"/&gt;
            &lt;/field&gt;
            &lt;field name="to" type="AirportBean"&gt;
            &lt;bind-xml name="to" node="attribute" reference="true"/&gt;
            &lt;/field&gt;
            &lt;field name="flights" type="FlightBean" collection="collection"&gt;
            &lt;bind-xml name="flight"/&gt;
            &lt;/field&gt;
            &lt;/class&gt;
            &lt;class name="FlightBean" auto-complete="true"&gt;
            &lt;field name="carrier"&gt;
            &lt;bind-xml name="carrier" node="attribute" reference="true"/&gt;
            &lt;/field&gt;
            &lt;field name="departureTime"&gt;
            &lt;bind-xml name="depart" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;field name="arrivalTime"&gt;
            &lt;bind-xml name="arrive" node="attribute"/&gt;
            &lt;/field&gt;
            &lt;/class&gt;
            &lt;/mapping&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>除了新增的 bean 之外，这里有一个重要的变化，就是增加了 <code>identity</code> 和 <code>reference</code> 属性。 <code>class</code> 元素的 <code>identity</code> 属性，通知 Castor 这个命名属性是该类实例的唯一标识符。在这里，我把 <code>CarrierBean</code> 和 <code>AirportBean</code> 的 <code>ident</code> 属性定义成它们的标识符。 </p>
<p><code>bind-xml</code> 元素的 <code>reference</code> 属性，提供了对于该映射 Castor 所需要的另一部分链接信息。 <code>reference</code> 设为 <code>true</code> 的映射告诉 Castor 编组和解组引用对象的标识符，而不是对象本身的副本。从 <code>RouteBean</code> 链接 <code>AirportBean</code> （表示航线的起止点）的引用，从 <code>FlightBean</code> 链接 <code>CarrierBean</code> 的引用，都使用了这种方法。 </p>
<p>当 Castor 使用这种类型的映射解组数据时，它自动把对象标识符转化为对实际对象的引用。您需要保证标识符的值确实是唯一的，甚至不同类型的对象之间也要保证这种唯一性。对于本例中的数据，这一点不成问题：飞机的标识符是两个字符，而机场的标识符是三个字符，永远不会冲突。如果 <em>确实</em>有潜在冲突的可能性，只要在所代表的对象类型的每个标识符加上唯一的前缀，就可以很容易地避免这种问题。 </p>
<p><a name="h12"><span class="smalltitle">编组后的时刻表</span></a></p>
<p>这个例子的测试代码没有新东西，只是增加了一些示例数据。清单 8 给出了编组形成的 XML 文档：</p>
<br />
<a name="code8"><strong>清单 8. 编组的时刻表</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;?xml version="1.0"?&gt;
            &lt;timetable&gt;
            &lt;carrier ident="AR" rating="9"&gt;
            &lt;URL&gt;http://www.arcticairlines.com&lt;/URL&gt;
            &lt;name&gt;Arctic Airlines&lt;/name&gt;
            &lt;/carrier&gt;
            &lt;carrier ident="CA" rating="7"&gt;
            &lt;URL&gt;http://www.combinedlines.com&lt;/URL&gt;
            &lt;name&gt;Combined Airlines&lt;/name&gt;
            &lt;/carrier&gt;
            &lt;airport ident="SEA"&gt;
            &lt;location&gt;Seattle, WA&lt;/location&gt;
            &lt;name&gt;Seattle-Tacoma International Airport&lt;/name&gt;
            &lt;/airport&gt;
            &lt;airport ident="LAX"&gt;
            &lt;location&gt;Los Angeles, CA&lt;/location&gt;
            &lt;name&gt;Los Angeles International Airport&lt;/name&gt;
            &lt;/airport&gt;
            &lt;route from="SEA" to="LAX"&gt;
            &lt;flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/&gt;
            &lt;flight carrier="CA" depart="8:10a" arrive="10:52a" number="833"/&gt;
            &lt;flight carrier="AR" depart="9:00a" arrive="11:36a" number="433"/&gt;
            &lt;/route&gt;
            &lt;route from="LAX" to="SEA"&gt;
            &lt;flight carrier="CA" depart="7:45a" arrive="10:20a" number="311"/&gt;
            &lt;flight carrier="AR" depart="9:27a" arrive="12:04p" number="593"/&gt;
            &lt;flight carrier="AR" depart="12:30p" arrive="3:07p" number="102"/&gt;
            &lt;/route&gt;
            &lt;/timetable&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="h13"><span class="atitle">使用数据</span></a></p>
<p>现在，时刻表中的所有数据都最终完成了，简单地看一看如何在程序中处理它们。使用数据绑定，您已经建立了时刻表的数据结构，它由几种类型的 bean 组成。处理数据的应用程序代码可以直接使用这些 bean。</p>
<p>比方说，假设您要查看在西雅图和洛杉矶之间有哪些航班可供选择，并且要求班机至少具备指定的最低品质评价级别。清单 9 给出了使用数据绑定 bean 结构获取这些信息的基本代码（完整的细节请参阅从 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources">参考资料</a>下载的源文件）。 </p>
<br />
<a name="code9"><strong>清单 9. 航班查找程序代码</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">private static void listFlights(TimeTableBean top, String from,
            String to, int rating) {
            // find the routes for outbound and inbound flights
            Iterator r_iter = top.getRoutes().iterator();
            RouteBean in = null;
            RouteBean out = null;
            while (r_iter.hasNext()) {
            RouteBean route = (RouteBean)r_iter.next();
            if (route.getFrom().getIdent().equals(from) &amp;&amp;
            route.getTo().getIdent().equals(to)) {
            out = route;
            } else if (route.getFrom().getIdent().equals(to) &amp;&amp;
            route.getTo().getIdent().equals(from)) {
            in = route;
            }
            }
            // make sure we found the routes
            if (in != null &amp;&amp; out != null) {
            // find outbound flights meeting carrier rating requirement
            Iterator o_iter = out.getFlights().iterator();
            while (o_iter.hasNext()) {
            FlightBean o_flight = (FlightBean)o_iter.next();
            if (o_flight.getCarrier().getRating() &gt;= rating) {
            // find inbound flights meeting carrier rating
            //  requirement, and leaving after outbound arrives
            int time = timeToMinute(o_flight.getArrivalTime());
            Iterator i_iter = in.getFlights().iterator();
            while (i_iter.hasNext()) {
            FlightBean i_flight = (FlightBean)i_iter.next();
            if (i_flight.getCarrier().getRating() &gt;= rating
            &amp;&amp;
            timeToMinute(i_flight.getDepartureTime())
            &gt; time) {
            // list the flight combination
            printFlights(o_flight, i_flight, from, to);
            }
            }
            }
            }
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>您可以尝试使用前面 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code8">清单 8</a>中的数据。如果您询问从西雅图（SEA）到洛杉矶（LAX）、级别大于或等于 8 的班机，就会得到如下的结果： </p>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">Leave SEA on Arctic Airlines 426 at 6:23a
            return from LAX on Arctic Airlines 593 at 9:27a
            Leave SEA on Arctic Airlines 426 at 6:23a
            return from LAX on Arctic Airlines 102 at 12:30p
            Leave SEA on Arctic Airlines 433 at 9:00a
            return from LAX on Arctic Airlines 102 at 12:30p</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><a name="h14"><span class="smalltitle">与文档模型的比较</span></a></p>
<p>这里我不准备全面讨论使用 XML 文档模型的等价代码，那太复杂了，足以单独成章。解决这个问题最简单的方式，可能是首先解析 <code>carrier</code> 元素，创建每个标识符代码到相应对象之间的映射链接。然后使用和 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code9">清单 9</a>中示例代码类似的逻辑。和使用 bean 的例子相比，每一步都更加复杂，因为代码使用的是 XML 成分而不是真正的数据值。性能可能更糟——只对数据进行少量的操作还不算是问题，但是如果数据处理是应用程序的核心，这就会成为一个主要的焦点。 </p>
<p>如果在 bean 和 XML 的映射中使用更多的数据类型转换，差别会更大（无论从代码的复杂性还是从性能的角度看）。比方说，假设您使用很多的航班时间，可能希望把文本时间转化成一种更好的国际化表示（如一天内的分钟数，参见 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code9">清单 9</a>）。您可以选择为文本和国际化格式定义可以替换的 <code>get</code> 和 <code>set</code> 方法（让映射仅仅使用文本形式），也可以定义一个定制的 <code>org.exolab.castor.mapping.FieldHandler</code> 实现让 Castor 使用这些值。保留时间值的内部形式，可以避免匹配清单 9 中的航班时进行转换，也许还能加快处理速度。 </p>
<p>除了本文中所述的之外—— <code>FieldHandler</code> 只是一个例子，Castor 还有许多迷人的特性。但愿这些例子和讨论使您能够初步领略这个框架的强大功能和灵活性。 我相信，您将和我一样发现 Castor 非常有用也非常有趣。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="h15"><span class="atitle">结束语</span></a></p>
<p>对于使用 XML 交换数据的应用程序，数据绑定是文档模型很好的替代品。它简化了编程，因为您不必再按照 XML 的方式思考。相反，您可以直接使用代表应用程序所用数据含义的对象。与文档模型相比，它还潜在地提供了更好的内存和处理器使用效率。</p>
<p>本文中，我使用 Castor 框架展示了一些越来越复杂的数据绑定的例子。所有这些例子都使用所谓的 <em>直接</em>数据绑定：开发人员根据数据定义类，然后把数据映射到 XML 文档结构。下一篇文章中，我将探讨另一种方法： <em>模式</em>数据绑定，利用模式（如 DTD、XML 模式或者其他的类型）生成和那个模式对应的代码。 </p>
<p>Castor 同时支持模式方法和本文中介绍的直接绑定，您将在以后看到更多的 Castor 应用。我还关注着 JSR-031 Java 数据绑定标准的进展，并对这些方法的性能进行比较。更多了解 Java 中的 XML 数据绑定这个领域，请速来访问离您最近的 IBM <em>developerWorks</em>。 </p>
 <img src ="http://www.blogjava.net/lcwlv929/aggbug/145063.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcwlv929/" target="_blank">炜</a> 2007-09-14 10:29 <a href="http://www.blogjava.net/lcwlv929/articles/145063.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Castor XML</title><link>http://www.blogjava.net/lcwlv929/articles/145061.html</link><dc:creator>炜</dc:creator><author>炜</author><pubDate>Fri, 14 Sep 2007 02:18:00 GMT</pubDate><guid>http://www.blogjava.net/lcwlv929/articles/145061.html</guid><wfw:comment>http://www.blogjava.net/lcwlv929/comments/145061.html</wfw:comment><comments>http://www.blogjava.net/lcwlv929/articles/145061.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcwlv929/comments/commentRss/145061.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcwlv929/services/trackbacks/145061.html</trackback:ping><description><![CDATA[<div id="art" style="margin: 15px" width="100%">一、 简介<br />
Castor XML是一种XML数据绑定框架。<br />
XML的另外两种主要API：DOM和SAX（Document Object Model和Simple API for XML），主要是从结构的角度去处理XML文件，而Castor XML是以对象的模式去处理XML文档中的数据
<p>大多数情况下，转换框架通过ClassDescriptor和FieldDescriptor来描述转换时所需要的信息。</p>
<p>二、 转换框架<br />
转换框架中最主要的两个类是：org.exolab.castor.xml.Marshaller和org.exolab.castor.xml.Unmarshaller</p>
<p>marshal: Marshaller.marshal(obj,writer);<br />
unmarshal: Unmarshaller.unmarshal(Person.class,reader);</p>
<p>上面的这种转换方式，只适合于按照默认方式进行转化，如果要使用映射文件，需要采用以下方式。<br />
marshal：<br />
Mapping mapping = new Mapping();<br />
mapping.loadMapping(&#8220;mapping.xml&#8221;);<br />
Marshaller marshaller = new Marshaller(writer);<br />
marshaller.setMapping(mapping);<br />
marshaller.marshal(obj);<br />
Marshaller的5个marshal方法中，只有marshal(Object obj)这个方法不是静态的，其他的四个都是静态的marshal(obj,writer), marshal(obj,handler), marshal(obj,node)</p>
<p>unmarshal：<br />
Mapping mapping = new Mapping();<br />
mapping .loadMapping(&#8220;mapping.xml&#8221;);<br />
Unmarshaller unm = new Unmarshaller(&#8220;Person.class&#8221;);//使用Person.class作为构造Unmarshaller的参数<br />
unm.setMapping(mapping);<br />
Person person = (Person)unm.unmarshal(reader);<br />
Unmarshaller中，object可以从reader中转换而来，也可以从source、node转换而来，静态方法均是两个参数，非静态方法都是一个来源作为参数。</p>
<p>三、 使用存在的Class和对象<br />
Castor几乎可以将任何对象和XML进行转换。当指定class的描述文件不存在时，转换框架使用默认的reflection机制来获得对象的信息。</p>
<p>转化对象存在的主要约束是：<br />
这些class必须有一个public而且default的构造函数；必须有adequate get/set方法。</p>
<p>四、 类描述符(ClassDescriptor)<br />
org.exolab.castor.xml.XMLClassDescriptor<br />
类描述符提供转换时所需的必要信息。ClassDescriptor不仅可以用于Castor XML，还可以用于Castor JDO</p>
<p>类描述符包括一组字段描述符(FieldDescriptor)</p>
<p>类描述符通常情况下有四种创建方式，两种在编译时(效率较高)，两种在运行时(较为方便)<br />
编译时描述符：<br />
1. 让需要被describe的类实现org.exolab.castor.xml.XMLClassDescriptor接口<br />
2. 使用Source Code Generator创建合适的descriptor<br />
运行时描述符：<br />
3. 默认，使用Castor的introspect机制<br />
4. 提供mapping文件，或者默认和配置文件并用</p>
<p>使用&#8221;default introspection&#8221;机制必须为每一个要转换的field配备对应的get/set方法；<br />
如果没有get/set方法，但是是public的field，也可以以direct field access的方式被转换；<br />
但是如果一个类中为有的成员定义了get/set方法，即使其他成员是public的，也不会被转换；<br />
自动内省机制是自动触发的。可以通过castor.properties文件控制自动转换的特性，比如改变名称转换、基本型别是转换为attribute还是element等。</p>
<p>Mapping文件也可以用来描述要被转换的类。mapping的装载发生在marshal和unmarshal之前（org.exolab.castor.mapping.Mapping）</p>
</div>
 <img src ="http://www.blogjava.net/lcwlv929/aggbug/145061.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcwlv929/" target="_blank">炜</a> 2007-09-14 10:18 <a href="http://www.blogjava.net/lcwlv929/articles/145061.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate.cfg.xml配置文件</title><link>http://www.blogjava.net/lcwlv929/articles/133538.html</link><dc:creator>炜</dc:creator><author>炜</author><pubDate>Tue, 31 Jul 2007 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/lcwlv929/articles/133538.html</guid><wfw:comment>http://www.blogjava.net/lcwlv929/comments/133538.html</wfw:comment><comments>http://www.blogjava.net/lcwlv929/articles/133538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcwlv929/comments/commentRss/133538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcwlv929/services/trackbacks/133538.html</trackback:ping><description><![CDATA[<span class=article_f14 id=zoom>&nbsp;&lt;?xml version="1.0" encoding="utf-8"?&gt;<br>&lt;!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "hibernate-configuration-2.0.dtd"&gt;<br>&lt;hibernate-configuration&gt;<br>&nbsp;&nbsp;&nbsp; &lt;session-factory&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- properties --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- jndi --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="connection.datasource"&gt;java:comp/env/jdbc/quickstart&lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="connection.provider_class"&gt;net.sf.hibernate.connection.DatasourceConnectionProvider&lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="dialect"&gt;net.sf.hibernate.dialect.SQLServerDialect&lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- jdbc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="connection.url"&gt;jdbc:microsoft:sqlserver://localhost:1433;SelectMethod=cursor;DatabaseName=pubs&lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="connection.driver_class"&gt;com.microsoft.jdbc.sqlserver.SQLServerDriver&lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="connection.username"&gt;sa&lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="connection.password"&gt;&lt;/property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="jdbc.fetch_size"&gt;50&lt;/property&gt;&lt;!-- 一次读的数据库记录数 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="jdbc.batch_size"&gt;30&lt;/property&gt;&lt;!-- 设定对数据库进行批量删除 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="show_sql"&gt;true&lt;/property&gt;&lt;!-- 将Hibernate发送给数据库的sql显示出来 --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- Mapping files --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;mapping resource="cat.hbm.xml"/&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/session-factory&gt;<br>&lt;/hibernate-configuration&gt;<br>
<p>数据库表主键的知识点：<br>Generator 为每个 POJO 的实例提供唯一标识。一般情况，我们使用&#8220;native&#8221;。class 表示采用由生成器接口net.sf.hibernate.id.IdentifierGenerator 实现的某个实例，其中包括：</p>
<br>
<p>&#8220;assigned&#8221;<br>主键由外部程序负责生成，在 save() 之前指定一个。</p>
<br>
<p>&#8220;hilo&#8221;<br>通过hi/lo 算法实现的主键生成机制，需要额外的数据库表或字段提供高位值来源。</p>
<br>
<p>&#8220;seqhilo&#8221;<br>与hilo 类似，通过hi/lo 算法实现的主键生成机制，需要数据库中的 Sequence，适用于支持 Sequence 的数据库，如Oracle。</p>
<br>
<p>&#8220;increment&#8221;<br>主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量，以保存着当前的最大值，之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是：不能在集群下使用。</p>
<br>
<p>&#8220;identity&#8221;<br>采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL 中的主键生成机制。</p>
<br>
<p>&#8220;sequence&#8221;<br>采用数据库提供的 sequence 机制生成主键。如 Oralce 中的Sequence。</p>
<br>
<p>&#8220;native&#8221;<br>由 Hibernate 根据使用的数据库自行判断采用 identity、hilo、sequence 其中一种作为主键生成方式。 </p>
<br>
<p>&#8220;uuid.hex&#8221;<br>由 Hibernate 基于128 位 UUID 算法 生成16 进制数值（编码后以长度32 的字符串表示）作为主键。</p>
<br>
<p>&#8220;uuid.string&#8221;<br>与uuid.hex 类似，只是生成的主键未进行编码（长度16），不能应用在 PostgreSQL 数据库中。</p>
<br>
<p>&#8220;foreign&#8221;<br>使用另外一个相关联的对象的标识符作为主键。</p>
<br>
<p>以下举例：<br>1、指定参数的情况：<br>&nbsp;&nbsp;&nbsp; &lt;id name="id" unsaved-value="0"&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="sequence"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="sequence"&gt;SEQ_CHILD&lt;/param&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/generator&gt;<br>&lt;/id&gt;<br>使用的是sequence，适合oracle数据库；</p>
<br>
<p>2、对于sql server2000中的数据库子增字段,在配置文件使用下列方法实现：<br>&lt;id name="id" type="long" unsaved-value="0"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; &lt;column name="id" sql-type="numeric" not-null="true" /&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="identity" /&gt; <br>&lt;/id&gt;<br>这里主要是:identity:代表由sql server2000数据库自己提供子增字段.如果要hibernate自己提供,则用increment关键字来实现</p>
<br>
<p>3、如果表中的主键用字符串类型:可以用hibernate自己提供的方法实现主键唯一:<br>&nbsp; &lt;id name="id" type="string" unsaved-value="null"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;column name="cid" sql-type="char(32)" not-null="true" /&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="uuid.hex" /&gt;<br>&nbsp; &lt;/id&gt;<br>使用的是uuid.hex: 采用128位的算法来生成一个32位字符串。最通用的一种方式。适用于所有数据库。</p>
<br>
<p>重要的知识点:<br>1. 如果有部门表,有员工表,员工表中有dep_id,则表部门类和员工类是one-to-many的关系:<br>&nbsp;&nbsp; 可以使用:&nbsp; ( 在部门类department中使用下列)<br>&nbsp;&nbsp; Department类:&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; 部门的所有员工&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; private Set staffs = new TreeSet();<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; xml的文件:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;set name="staffs" &gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key column="dep_id"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;one-to-many class="hbp.sys.data.Staff"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果是list,需要用索引&lt;index&gt; &lt;/index&gt;,具体其中的含义,不是很明白.待以后研究<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;2. 如果部门要有一个负责人,即部门表(tb_department)中有一个字段:staff_id.<br>&nbsp;&nbsp;&nbsp;&nbsp; 那么表示部门和负责人之间的关系是many-to-one的关系<br>&nbsp;&nbsp;&nbsp;&nbsp; Department类: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** 部门负责人id */<br>&nbsp;&nbsp;&nbsp; private Staff staff;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; xml 文件<br>&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-one name="staff" class="hbp.sys.data.Staff"&nbsp; column="staff_id"/&gt;&nbsp; <br>&nbsp; <br>&nbsp;3. 多对多关系,一般我们是做一个中间关联表.我用角色和权限做了个例子,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Right(id,name)&nbsp;&nbsp;&nbsp;&nbsp; Role(id,name)&nbsp;&nbsp; 中间表:tb_role_right(role_id,right_id)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Right类中有一个Role的集合:private Set roles=new TreeSet();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Role类中也有一个Right的集合:private Set rights=new TreeSet();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 则两者是明显的多对多关系.使用many-to-many来实现;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xml文件中<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; right.hbm.xml:如下:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;set name="roles" table="tb_role_right" cascade="all"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key column="right_id"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-many column="role_id" class="hbp.sys.data.Role"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; role.hbm.xml文件中类似:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;set name="rights" table="tb_role_right" cascade="all"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key column="role_id"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-many column="right_id" class="hbp.sys.data.Right"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt; </p>
<br>
<p>4. 几个值得注意的问题:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a)在xml?映射文件中,写类的名字时一定用类的全名:即:包+类名如:(hbp.sys.data.Staff),这个错误使我费了半天劲.:(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b)我在写实现基本DAO操作时,写了<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.delete("from Right as right where right.id="+id);&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 程序死活报错,我折腾了半天,跟踪到底,才恍然大悟,hibernate在解析sql语句的时候把<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中的right,当成了数据库中的右连接("保留字"),唉,这种关键字,不能随便用啊,:)</p>
<br>
<p>5. hibernate中HQL语言的查询根据你的sql的不同而返回不同的对象类型.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你使用session.find(String hql)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一般会返回一个List,如:from Staff staff;返回的是包含所有的员工对象的集合<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如你的hql为:select count(*) from Staff staff;则返回的是一个Integer对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你使用的hql为:select count(distinct staff.name),count(*) from Staff staff;则返回的是一个Object<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 即Object[],需要先把他转换成Object[],然后在取[0],[1].<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这种设计我不知道hibernate是如何处理的,感觉既好也不好.好的是可以使用一个find获得任意查询<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不好在于根据hql来处理返回结果,容易出错.</p>
</span>
 <img src ="http://www.blogjava.net/lcwlv929/aggbug/133538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcwlv929/" target="_blank">炜</a> 2007-07-31 11:47 <a href="http://www.blogjava.net/lcwlv929/articles/133538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>