﻿<?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-生活源于奋斗不息-随笔分类-Java</title><link>http://www.blogjava.net/site120/category/18141.html</link><description>凝聚，积累，量变……  &lt;b&gt;心领神会，勤加练习！&lt;/b&gt; 大处着眼，小处着手。</description><language>zh-cn</language><lastBuildDate>Sat, 17 Nov 2007 12:02:56 GMT</lastBuildDate><pubDate>Sat, 17 Nov 2007 12:02:56 GMT</pubDate><ttl>60</ttl><item><title>远程方法调用入门指南</title><link>http://www.blogjava.net/site120/archive/2007/11/08/159203.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Thu, 08 Nov 2007 15:25:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/11/08/159203.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/159203.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/11/08/159203.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/159203.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/159203.html</trackback:ping><description><![CDATA[<div><a></a>
<h3><a><font color="#0066a7">Stephen Suen</font> </a></h3>
</div>
<p>Copyright &#169; 2005 Stephen Suen. All rights reserved. </p>
<div>
<div>
<p><a></a></p>
<p>Java 远程方法调用（Remote Method Invocation, RMI）使得运行在一个 Java 虚拟机（Java Virtual Machine, JVM）的对象可以调用运行另一个 JVM 之上的其他对象的方法，从而提供了程序间进行远程通讯的途径。RMI 是 J2EE 的很多分布式技术的基础，比如 RMI-IIOP 乃至 EJB。本文是 RMI 的一个入门指南，目的在于帮助读者快速建立对 Java RMI 的一个感性认识，以便进行更深层次的学习。事实上，如果你了解 RMI 的目的在于更好的理解和学习 EJB，那么本文就再合适不过了。通过本文所了解的 RMI 的知识和技巧，应该足够服务于这个目的了。 </p>
<p>&nbsp;</p>
</div>
</div>
<div></div>
<div>
<h1><a><font color="#0066a7">1. 简介</font> </a></h1>
<p>我们知道远程过程调用（Remote Procedure Call, RPC）可以用于一个进程调用另一个进程（很可能在另一个远程主机上）中的<span><em>过程</em></span>，从而提供了过程的分布能力。Java 的 RMI 则在 RPC 的基础上向前又迈进了一步，即提供分布式<span><em> 对象</em></span>间的通讯，允许我们获得在远程进程中的对象（称为远程对象）的引用（称为远程引用），进而通过引用调用远程对象的方法，就好像该对象是与你的客户端代码同样运行在本地进程中一样。RMI 使用了术语"方法"（Method）强调了这种进步，即在分布式基础上，充分支持面向对象的特性。 </p>
<p>RMI 并不是 Java 中支持远程方法调用的唯一选择。在 RMI 基础上发展而来的 RMI-IIOP（Java Remote Method Invocation over the Internet Inter-ORB Protocol），不但继承了 RMI 的大部分优点，并且可以兼容于 CORBA。J2EE 和 EJB 都要求使用 RMI-IIOP 而不是 RMI。尽管如此，理解 RMI 将大大有助于 RMI-IIOP 的理解。所以，即便你的兴趣在 RMI-IIOP 或者 EJB，相信本文也会对你很有帮助。另外，如果你现在就对 API 感兴趣，那么可以告诉你，RMI 使用 <font color="red">java.rmi</font> 包，而 RMI-IIOP 则既使用 <font color="red">java.rmi</font> 也使用扩展的 <font color="red">javax.rmi</font> 包。 </p>
<p>本文的随后内容将仅针对 Java RMI。</p>
</div>
<div>
<h1><a><font color="#0066a7">2. 分布式对象</font> </a></h1>
<p>在学习 RMI 之前，我们需要了解一些基础知识。首先需要了解所谓的分布式对象（Distributed Object）。分布式对象是指一个对象可以被远程系统所调用。对于 Java 而言，即对象不仅可以被同一虚拟机中的其他客户程序（Client）调用，也可以被运行于其他虚拟机中的客户程序调用，甚至可以通过网络被其他远程主机之上的客户程序调用。 </p>
<p>下面的图示说明了客户程序是如何调用分布式对象的： </p>
<div>
<p><img alt="" src="http://storage.msn.com/x1pGg9EMswqL--KyzGRGdhRjrq64UqttMM_PJCibCwwE4IdiYXO1md4zsjx996jvYuxnudo29e0GI0ry5z7KlGOWTxiA7t3Y3D5evWkQ8tZPfazDTvArq--pvMKaUlc__RNmlIlOq5vY-H0Kl2N47CivQ" /> </p>
</div>
<p>从图上我们可以看到，分布式对象被调用的过程是这样的： </p>
<p>&nbsp;</p>
<ol>
    <li>
    <p>客户程序调用一个被称为 Stub （有时译作存根，为了不产生歧义，本文将使用其英文形式）的客户端代理对象。该代理对象负责对客户端隐藏网络通讯的细节。Stub 知道如何通过网络套接字（Socket）发送调用，包括如何将调用参数转换为适当的形式以便传输等。 </p>
    <li>
    <p>Stub 通过网络将调用传递到服务器端，也就是分布对象一端的一个被称为 Skeleton 的代理对象。同样，该代理对象负责对分布式对象隐藏网络通讯的细节。Skeleton 知道如何从网络套接字（Socket）中接受调用，包括如何将调用参数从网络传输形式转换为 Java 形式等。 </p>
    <li>
    <p>Skeleton 将调用传递给分布式对象。分布式对象执行相应的调用，之后将返回值传递给 Skeleton，进而传递到 Stub，最终返回给客户程序。</p>
    </li>
</ol>
<p>这个场景基于一个基本的法则，即行为的定义和行为的具体实现相分离。如图所示，客户端代理对象 Stub 和分布式对象都实现了相同的接口，该接口称为远程接口（Remote Interface）。正是该接口定义了行为，而分布式对象本身则提供具体的实现。对于 Java RMI 而言，我们用接口（<font color="red">interface</font>）定义行为，用类（<font color="red">class</font>）定义实现。 </p>
</div>
<div>
<h1><a><font color="#0066a7">3. RMI 架构</font> </a></h1>
<p>RMI 的底层架构由三层构成： </p>
<p>&nbsp;</p>
<ul>
    <li>
    <p>首先是 Stub/Skeleton 层。该层提供了客户程序和服务程序彼此交互的接口。 </p>
    <li>
    <p>然后是远程引用（Remote Reference）层。这一层相当于在其之上的 Stub/Skeleton 层和在其之下的传输协议层之前的中间件，负责处理远程对象引用的创建和管理。 </p>
    <li>
    <p>最后是传输协议（Transport Protocol） 层。该层提供了数据协议，用以通过线路传输客户程序和远程对象间的请求和应答。</p>
    </li>
</ul>
<p>这些层之间的交互可以参照下面的示意图： </p>
<div>
<p><img alt="" src="http://storage.msn.com/x1pGg9EMswqL--KyzGRGdhRjrq64UqttMM_PJCibCwwE4LYc9TR44YWI1mMQE5aQp9ot9OjPBDKWlfamAjUBUEv9B78DuzO6uk_6mbUokjRpiHZnuy_Vhk1YzAUlzbLdD0LfHsABLa8zbukz397rrHcWccZDZQyoGBG" /> </p>
</div>
<p>和其它分布式对象机制一样，Java RMI 的客户程序使用客户端的 Stub 向远程对象请求方法调用；服务器对象则通过服务器端的 Skeleton 接受请求。我们深入进去，来看看其中的一些细节。 </p>
<div>
<blockquote>
<p><strong>注意: </strong>事实上，在 Java 1.2 之后，RMI 不再需要 Skeleton 对象，而是通过 Java 的反射机制（Reflection）来完成对服务器端的远程对象的调用。为了便于说明问题，本文以下内容仍然基于 Skeleton 来讲解。</p>
</blockquote></div>
<p>当客户程序调用 Stub 时，Stub 负责将方法的参数转换为序列化（Serialized）形式，我们使用一个特殊的术语，即编列（Marshal）来指代这个过程。编列的目的是将这些参数转换为可移植的形式，从而可以通过网络传输到远程的服务对象一端。不幸的是，这个过程没有想象中那么简单。这里我们首先要理解一个经典的问题，即方法调用时，参数究竟是传值还是传引用呢？对于 Java RMI 来说，存在四种情况，我们将分别加以说明。 </p>
<p>&nbsp;</p>
<ul>
    <li>
    <p>对于基本的原始类型（整型，字符型等等），将被自动的序列化，以传值的方式编列。 </p>
    <li>
    <p>对于 Java 的对象，如果该对象是可序列化的（实现了 <font color="red">java.io.Serializable</font> 接口），则通过 Java 序列化机制自动地加以序列化，以传值的方式编列。对象之中包含的原始类型以及所有被该对象引用，且没有声明为 <font color="red">transient</font> 的对象也将自动的序列化。当然，这些被引用的对象也必须是可序列化的。 </p>
    <li>
    <p>绝大多数内建的 Java 对象都是可序列化的。 对于不可序列化的 Java 对象（<font color="red">java.io.File</font> 最典型），或者对象中包含对不可序列化，且没有声明为 <font color="red">transient</font> 的其它对象的引用。则编列过程将向客户程序抛出异常，而宣告失败。 </p>
    <li>
    <p>客户程序可以调用远程对象，没有理由禁止调用参数本身也是远程对象（实现了 <font color="red">java.rmi.Remote</font> 接口的类的实例）。此时，RMI 采用一种<span><em>模拟的</em></span>传引用方式（当然不是传统意义的传引用，因为本地对内存的引用到了远程变得毫无意义），而不是将参数直接编列复制到远程。这种情况下，交互的双方发生的戏剧性变化值得我们注意。参数是远程对象，意味着该参数对象可以远程调用。当客户程序指定远程对象作为参数调用服务器端远程对象的方法时，RMI 的运行时机制将向服务器端的远程对象发送作为参数的远程对象的一个 Stub 对象。这样服务器端的远程对象就可以回调（Callback）这个 Stub 对象的方法，进而调用在客户端的远程对象的对应方法。通过这种方法，服务器端的远程对象就可以修改作为参数的客户端远程对象的内部状态，这正是传统意义的传引用所具备的特性。是不是有点晕？这里的关键是要明白，在分布式环境中，所谓服务器和客户端都是相对的。被请求的一方就是服务器，而发出请求的一方就是客户端。 </p>
    </li>
</ul>
<p>在调用参数的编列过程成功后，客户端的远程引用层从 Stub 那里获得了编列后的参数以及对服务器端远程对象的远程引用（参见 <font color="red">java.rmi.server.RemoteRef</font> API）。该层负责将客户程序的请求依据底层的 RMI 数据传输协议转换为传输层请求。在 RMI 中，有多种的可能的传输机制，比如点对点（Point-to-Point）以及广播（Multicast）等。不过，在当前的 JMI 版本中只支持点对点协议，即远程引用层将生成唯一的传输层请求，发往指定的唯一远程对象（参见 <font color="red">java.rmi.server.UnicastRemoteObject</font> API）。 </p>
<p>在服务器端，服务器端的远程引用层接收传输层请求，并将其转换为对远程对象的服务器端代理对象 Skeleton 的调用。Skeleton 对象负责将请求转换为对实际的远程对象的方法调用。这是通过与编列过程相对的反编列（Unmarshal）过程实现的。所有序列化的参数被转换为 Java 形式，其中作为参数的远程对象（实际上发送的是远程引用）被转换为服务器端本地的 Stub 对象。 </p>
<p>如果方法调用有返回值或者抛出异常，则 Skeleton 负责编列返回值或者异常，通过服务器端的远程引用层，经传输层传递给客户端；相应地，客户端的远程引用层和 Stub 负责反编列并最终将结果返回给客户程序。 </p>
<p>整个过程中，可能最让人迷惑的是远程引用层。这里只要明白，本地的 Stub 对象是如何产生的，就不难理解远程引用的意义所在了。远程引用中包含了其所指向的远程对象的信息，该远程引用将用于构造作为本地代理对象的 Stub 对象。构造后，Stub 对象内部将维护该远程引用。真正在网络上传输的实际上就是这个远程引用，而不是 Stub 对象。</p>
</div>
<div>
<h1><a><font color="#0066a7">4. RMI 对象服务</font> </a></h1>
<p>在 RMI 的基本架构之上，RMI 提供服务与分布式应用程序的一些对象服务，包括对象的命名/注册（Naming/Registry）服务，远程对象激活（Activation）服务以及分布式垃圾收集（Distributed Garbage Collection, DGC）。作为入门指南，本文将指介绍其中的命名/注册服务，因为它是实战 RMI 所必备的。其它内容请读者自行参考其它更加深入的资料。 </p>
<p>在前一节中，如果你喜欢刨根问底，可能已经注意到，客户端要调用远程对象，是通过其代理对象 Stub 完成的，那么 Stub 最早是从哪里得来的呢？RMI 的命名/注册服务正是解决这一问题的。当服务器端想向客户端提供基于 RMI 的服务时，它需要将一个或多个远程对象注册到本地的 RMI 注册表中（参见<font color="red">java.rmi.registry.Registry</font> API）。每个对象在注册时都被指定一个将来用于客户程序引用该对象的名称。客户程序通过命名服务（参见 <font color="red">java.rmi.Naming</font> API），指定类似 URL 的对象名称就可以获得指向远程对象的远程引用。在 <font color="red">Naming</font> 中的 <font color="red">lookup()</font> 方法找到远程对象所在的主机后，它将检索该主机上的 RMI 注册表，并请求所需的远程对象。如果注册表发现被请求的远程对象，它将生成一个对该远程对象的远程引用，并将其返回给客户端，客户端则基于远程引用生成相应的 Stub 对象，并将引用传递给调用者。之后，双方就可以按照我们前面讲过的方式进行交互了。 </p>
<div>
<blockquote>
<p><strong>注意: </strong>RMI 命名服务提供的 <font color="red">Naming</font> 类并不是你的唯一选择。RMI 的注册表可以与其他命名服务绑定，比如 JNDI，这样你就可以通过 JNDI 来访问 RMI 的注册表了。</p>
</blockquote></div>
</div>
<div>
<h1><a><font color="#0066a7">5. 实战 RMI</font> </a></h1>
<p>理论离不开实践，理解 RMI 的最好办法就是通过例子。开发 RMI 的分布式对象的大体过程包括如下几步： </p>
<p>&nbsp;</p>
<ol>
    <li>
    <p>定义远程接口。这一步是通过扩展 <font color="red">java.rmi.Remote</font> 接口，并定义所需的业务方法实现的。 </p>
    <li>
    <p>定义远程接口的实现类。即实现上一步所定义的接口，给出业务方法的具体实现逻辑。 </p>
    <li>
    <p>编译远程接口和实现类，并通过 RMI 编译器 <strong>rmic</strong> 基于实现类生成所需的 Stub 和 Skeleton 类。</p>
    </li>
</ol>
<p>RMI 中各个组件之间的关系如下面这个示意图所示： </p>
<div>
<p><img alt="" src="http://storage.msn.com/x1pGg9EMswqL--KyzGRGdhRjrq64UqttMM_PJCibCwwE4JxA-aX-SZD0hjjnO9OG_VQQMz7HdUngz_LHForXB2I2mTv509Lxg9BFNumeHviSDXogOWKhYd19lHUSUiy6q91gU2yB69bThJI89K6hoqnkg" /> </p>
</div>
<p>回忆我们上一节所讲的，Stub 和 Skeleton 负责代理客户和服务器之间的通讯。但我们并不需要自己生成它们，相反，RMI 的编译器 <strong>rmic</strong> 可以帮我们基于远程接口和实现类生成这些类。当客户端对象通过命名服务向服务器端的 RMI 注册表请求远程对象时，RMI 将自动构造对应远程对象的 Skeleton 实例对象，并通过 Skeleton 对象将远程引用返回给客户端。在客户端，该远程引用将用于构造 Stub 类的实例对象。之后，Stub 对象和 Skeleton 对象就可以代理客户对象和远程对象之间的交互了。 </p>
<p>我们的例子展现了一个简单的应用场景。服务器端部署了一个计算引擎，负责接受来自客户端的计算任务，在服务器端执行计算任务，并将结果返回给客户端。客户端将发送并调用计算引擎的计算任务实际上是计算指定精度的 &#960; 值。 </p>
<div>
<blockquote>
<p><strong>重要: </strong>本文的例子改编自 <a href="http://java.sun.com/docs/books/tutorial/rmi/index.html"><font color="#0066a7">The Java&#8482; Tutorial Trail:RMI</font></a>。所有权利属于相应的所有人。</p>
</blockquote></div>
</div>
<div>
<h1><a><font color="#0066a7">6. 定义远程接口</font> </a></h1>
<p>定义远程接口与非分布式应用中定义接口的方法没有太多的区别。只要遵守下面两个要求： </p>
<p>&nbsp;</p>
<ul>
    <li>
    <p>远程接口必须直接或者间接的扩展自 <font color="red">java.rmi.Remote</font> 接口。远程接口还可以在扩展该接口的基础上，同时扩展其它接口，只要被扩展的接口的所有方法与远程接口的所有方法一样满足下一个要求。 </p>
    <li>
    <p>在远程接口或者其超接口（Super-interface）中声明的方法必须满足下列对<span><em>远程方法</em></span>的要求： </p>
    <p>&nbsp;</p>
    <ul>
        <li>
        <p>远程方法必须声明抛出 <font color="red">java.rmi.RemoteException</font> 异常，或者该异常的超类（Superclass），比如 <font color="red">java.io.IOException</font> 或者 <font color="red">java.lang.Exception</font> 异常。在此基础上，远程方法可以声明抛出应用特定的其它异常。 </p>
        <li>
        <p>在远程方法声明中，作为参数或者返回值的远程对象，或者包含在其它非远程对象中的远程对象，必须声明为其对应的远程接口，而不是实际的实现类。</p>
        </li>
    </ul>
    </li>
</ul>
<ul></ul>
    <div>
    <blockquote>
    <p><strong>注意: </strong>在 Java 1.2 之前，上面关于抛出异常的要求更严格，即必须抛出 <font color="red">java.rmi.RemoteExcption</font>，不允许类似 <font color="red">java.io.IOException</font> 这样的超类。现在之所以放宽了这一要求，是希望可以使定义既可以用于远程对象，也可以用于本地对象的接口变得容易一些（想想 EJB 中的本地接口和远程接口）。当然，这并没有使问题好多少，你还是必须声明异常。不过，一种观点认为这不是问题，强制声明异常可以使开发人员保持清醒的头脑，因为远程对象和本地对象在调用时传参的语意是不同的。本地对象是传引用，而远程对象主要是传值，这意味对参数内部状态的修改产生的结果是不同的。 </p>
    </blockquote></div>
    <p>对于第一个要求，<font color="red">java.rmi.Remote</font> 接口实际上没有任何方法，而只是用作标记接口。RMI 的运行环境依赖该接口判断对象是否是远程对象。第二个要求则是因为分布式应用可能发生任何问题，比如网络问题等等。 </p>
    <p><a><font color="#0066a7">例 1</font> </a>列出了我们的远程接口定义。该接口只有一个方法：<font color="red">executeTask()</font> 用以执行指定的计算任务，并返回相应的结果。注意，我们用后缀 <tt>Remote</tt> 表明接口是远程接口。 </p>
    <div><a></a>
    <p><strong>例 1. ComputeEngineRemote 远程接口</strong> <a></a></p>
    <blockquote>
    <pre>package rmitutorial;
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    public interface ComputeEngineRemote extends Remote {
    public Object executeTask(Task task) throws RemoteException;
    }</pre>
    </blockquote></div>
    <p><a><font color="#0066a7">例 2</font> </a>列出了计算任务接口的定义。该接口也只有一个方法：<font color="red">execute()</font> 用以执行实际的计算逻辑，并返回结果。注意，该接口不是远程接口，所以没有扩展 <font color="red">java.rmi.Remote</font> 接口；其方法也不必抛出 <font color="red">java.rmi.RemoteException</font> 异常。但是，因为它将用作远程方法的参数，所以扩展了 <font color="red">java.io.Serializable</font> 接口。 </p>
    <div><a></a>
    <p><strong>例 2. Task 接口</strong> <a></a></p>
    <blockquote>
    <pre>package rmitutorial;
    import java.io.Serializable;
    public interface Task extends Serializable {
    Object execute();
    }</pre>
    </blockquote></div>
    </div>
    <div>
    <h1><a><font color="#0066a7">7. 实现远程接口</font> </a></h1>
    <p>接下来，我们将实现前面定义的远程接口。<a><font color="#0066a7">例 3</font></a>给出了实现的源代码。 </p>
    <div><a></a>
    <p><strong>例 3. ComputeEngine 实现</strong> <a></a></p>
    <blockquote>
    <pre>package rmitutorial;
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    public class ComputeEngine extends UnicastRemoteObject
    implements ComputeEngineRemote {
    public ComputeEngine() throws RemoteException {
    super();
    }
    public Object executeTask(Task task) throws RemoteException {
    return task.execute();
    }
    }</pre>
    </blockquote></div>
    <p>类 <font color="red">ComputeEngine</font> 实现了之前定义的远程接口，同时继承自 <font color="red">java.rmi.server.UnicastRemoteObject</font> 超类。<font color="red">UnicastRemoteObject</font> 类是一个便捷类，它实现了我们前面所讲的基于 TCP/IP 的点对点通讯机制。远程对象都必须从该类扩展（除非你想自己实现几乎所有 <font color="red">UnicastRemoteObject</font> 的方法）。在我们的实现类的构造函数中，调用了超类的构造函数（当然，即使你不显式的调用这个构建函数，它也一样会被调用。这里这样做，只是为了突出强调这种调用而已）。该构造函数的最重要的意义就是调用 <font color="red">UnicastRemoteObject</font> 类的 <font color="red">exportObject() </font>方法。导出（Export）对象是指使远程对象准备就绪，可以接受进来的调用的过程。而这个过程的最重要内容就是建立服务器套接字，监听特定的端口，等待客户端的调用请求。</p>
    </div>
    <div>
    <h1><a><font color="#0066a7">8. 引导程序</font> </a></h1>
    <p>为了让客户程序可以找到我们的远程对象，就需要将我们的远程对象注册到 RMI 的注册表。这个过程有时被称为"引导"过程（Bootstrap）。我们将为此编写一个独立的引导程序负责创建和注册远程对象。<a><font color="#0066a7">例 4</font></a> 给出了引导程序的源代码。 </p>
    <div><a></a>
    <p><strong>例 4. 引导程序</strong> <a></a></p>
    <blockquote>
    <pre>package rmitutorial;
    import java.rmi.Naming;
    import java.rmi.RMISecurityManager;
    public class Bootstrap {
    public static void main(String[] args) throws Exception {
    String name = "ComputeEngine";
    ComputeEngine engine = new ComputeEngine();
    System.out.println("ComputerEngine exported");
    Naming.rebind(name, engine);
    System.out.println("ComputeEngine bound");
    }
    }
    </pre>
    </blockquote></div>
    <p>可以看到，我们首先创建了一个远程对象（同时导出了该对象），之后将该对象绑定到 RMI 注册表中。<font color="red">Naming</font> 的 <font color="red">rebind()</font> 方法接受一个 URL 形式的名字作绑定之用。其完整格式如下：<a></a></p>
    <blockquote>
    <p><a><font color="#0066a7">protocol://host:port/object</font> </a></p>
    </blockquote>
    <p>其中，协议（Protocol）默认为 <span>rmi</span>；主机名默认为 <span>localhost</span>；端口默认为 <tt>1099</tt>。注意，JDK 中提供的默认 <font color="red">Naming</font> 实现只支持 <span>rmi</span> 协议。在我们的引导程序里面只给出了对象绑定的名字，而其它部分均使用缺省值。</p>
    </div>
    <div>
    <h1><a><font color="#0066a7">9. 客户端程序</font> </a></h1>
    <p><a><font color="#0066a7">例 5</font> </a>给出了我们的客户端程序。该程序接受两个参数，分别是远程对象所在的主机地址和希望获得的 &#960; 值的精度。 </p>
    <div><a></a>
    <p><strong>例 5. Client.java</strong> <a></a></p>
    <blockquote>
    <pre>package rmitutorial;
    import java.math.BigDecimal;
    import java.rmi.Naming;
    public class Client {
    public static void main(String args[]) throws Exception {
    String name = "rmi://" + args[0] + "/ComputeEngine";
    ComputeEngineRemote engineRemote =
    (ComputeEngineRemote)Naming.lookup(name);
    Pi task = new Pi(Integer.parseInt(args[1]));
    BigDecimal pi = (BigDecimal)(engineRemote.executeTask(task));
    System.out.println(pi);
    }
    }</pre>
    </blockquote></div>
    <div><a></a>
    <p><strong>例 6. Pi.java</strong> <a></a></p>
    <blockquote>
    <pre>package rmitutorial;
    import java.math.*;
    public class Pi implements Task {
    private static final BigDecimal ZERO =
    BigDecimal.valueOf(0);
    private static final BigDecimal  ONE =
    BigDecimal.valueOf(1);
    private static final BigDecimal FOUR =
    BigDecimal.valueOf(4);
    private static final int roundingMode =
    BigDecimal.ROUND_HALF_EVEN;
    private int digits;
    public Pi(int digits) {
    this.digits = digits;
    }
    public Object execute() {
    return computePi(digits);
    }
    public static BigDecimal computePi(int digits) {
    int scale = digits + 5;
    BigDecimal arctan1_5 = arctan(5, scale);
    BigDecimal arctan1_239 = arctan(239, scale);
    BigDecimal pi = arctan1_5.multiply(FOUR).subtract(
    arctan1_239).multiply(FOUR);
    return pi.setScale(digits,
    BigDecimal.ROUND_HALF_UP);
    }
    public static BigDecimal arctan(int inverseX,
    int scale) {
    BigDecimal result, numer, term;
    BigDecimal invX = BigDecimal.valueOf(inverseX);
    BigDecimal invX2 =
    BigDecimal.valueOf(inverseX * inverseX);
    numer = ONE.divide(invX, scale, roundingMode);
    result = numer;
    int i = 1;
    do {
    numer =
    numer.divide(invX2, scale, roundingMode);
    int denom = 2 * i + 1;
    term =
    numer.divide(BigDecimal.valueOf(denom),
    scale, roundingMode);
    if ((i % 2) != 0) {
    result = result.subtract(term);
    } else {
    result = result.add(term);
    }
    i++;
    } while (term.compareTo(ZERO) != 0);
    return result;
    }
    }</pre>
    </blockquote></div>
    </div>
    <div>
    <h1><a><font color="#0066a7">10. 编译示例程序</font> </a></h1>
    <p>编译我们的示例程序和编译其它非分布式的应用没什么区别。只是编译之后，需要使用 RMI 编译器，即 <strong>rmic</strong> 生成所需 Stub 和 Skeleton 实现。使用 <strong>rmic</strong> 的方式是将我们的远程对象的实现类（不是远程接口）的全类名作为参数来运行 <strong>rmic</strong> 命令。参考下面的示例：<a></a></p>
    <blockquote>
    <pre>E:\classes\rmic rmitutorial.ComputeEngine</pre>
    </blockquote>
    <p>编译之后将生成 <font color="red">rmitutorial.ComputeEngine_Skel</font> 和 <font color="red">rmitutorial.ComputeEngine_Stub</font> 两个类。</p>
    </div>
    <div>
    <h1><a><font color="#0066a7">11. 运行示例程序</font> </a></h1>
    <p>远程对象的引用通常是通过 RMI 的注册表服务以及 <font color="red">java.rmi.Naming</font> 接口获得的。远程对象需要导出（注册）相应的远程引用到注册表服务，之后注册表服务就可以监听并服务于客户端对远程对象引用的请求。标准的 Sun Java SDK 提供了一个简单的 RMI 注册表服务程序，即 <strong>rmiregistry</strong> 用于监听特定的端口，等待远程对象的注册，以及客户端对这些远程对象引用的检索请求。 </p>
    <p>在运行我们的示例程序之前，首先要启动 RMI 的注册表服务。这个过程很简单，只要直接运行 <strong>rmiregistry</strong> 命令即可。缺省的情况下，该服务将监听 <tt>1099</tt> 端口。如果需要指定其它的监听端口，可以在命令行指定希望监听的端口（如果你指定了其它端口，需要修改示例程序以适应环境）。如果希望该程序在后台运行，在 Unix 上可以以如下方式运行（当然，可以缺省端口参数）： <a></a></p>
    <blockquote>
    <pre>$ rmiregistry 1099 &amp;</pre>
    </blockquote>
    <p>在 Windows 操作系统中可以这样运行：<a></a></p>
    <blockquote>
    <pre>C:\&gt; start rmiregistry 1099</pre>
    </blockquote>
    <p>我们的 <font color="red">rmitutorial.Bootstrap</font> 类将用于启动远程对象，并将其绑定在 RMI 注册表中。运行该类后，远程对象也将进入监听状态，等待来自客户端的方法调用请求。<a></a></p>
    <blockquote>
    <pre>$ java rmitutorial.Bootstrap
    ComputeEngine exported
    ComputeEngine bound</pre>
    </blockquote>
    <p>启动远程对象后，打开另一个命令行窗口，运行客户端。命令行的第一个参数为 RMI 注册表的地址，第二个参数为期望的 &#960; 值精度。参考下面的示例：<a></a></p>
    <blockquote>
    <pre>$ java rmitutorial.Client localhost 50
    3.14159265358979323846264338327950288419716939937511</pre>
    </blockquote></div>
    <div>
    <h1><a><font color="#0066a7">12. 其它信息</font> </a></h1>
    <p>在演示示例程序时，我们实际上是在同一主机上运行的服务器和客户端，并且无论是服务器和客户端所需的类都在相同的类路径上，可以同时被服务器和客户端所访问。这忽略了 Java RMI 的一个重要细节，即动态类装载。因为 RMI 的特性（包括其它几个特性）并不适用于 J2EE 的 RMI-IIOP 和 EJB 技术，所以，本文将不作详细介绍，请读者自行参考本文给出的参考资料。不过，为了让好奇的读者不至于过分失望，这里简单介绍一下动态类装载的基本思想。 </p>
    <p>RMI 运行时系统采用动态类装载机制来装载分布式应用所需的类。如果你可以直接访问应用所涉及的所有包括服务器端客户端在内的主机，并且可以把分布式应用所需的所有类都安装在每个主机的 <code>CLASSPATH</code> 中（上面的示例就是极端情况，所有的东西都在本地主机），那么你完全不必关心 RMI 类装载的细节。显然，既然是分布式应用，情况往往正相反。对于 RMI 应用，客户端需要装载客户端自身所需的类，将要调用的远程对象的远程接口类以及对应的 Stub 类；服务器端则要装载远程对象的实现类以及对应的 Skeleton 类（Java 1.2 之后不需要 Skeleton 类）。RMI 在处理远程调用涉及的远程引用，参数以及返回值时，可以将一个指定的 URL 编码到流中。交互的另一端可以通过 该 URL 获得处理这些对象所需的类文件。这一点类似于 Applet 中的 CODEBASE 的概念，交互的两端通过 HTTP 服务器发布各自控制的类，允许交互的另一端动态下载这些类。以我们的示例为例，客户端不必部署 <font color="red">ComputeEngine_Stub </font>的类文件，而可以通过服务器端的 HTTP 服务器获得类文件。同样，服务器端也不需要客户端实现的定制任务 <font color="red">Pi</font> 的类文件。 </p>
    <p>注意，这种动态类装载将需要交互的两端加载定制的安全管理器（参见 <font color="red">java.rmi.RMISecurityManager</font> API），以及对应的策略文件。</p>
    </div>
    <div>
    <h1><a><font color="#0066a7">13. 参考资料</font> </a></h1>
    <p><font color="#0066a7"></font></p>
    <ul>
        <li>
        <p><a href="http://java.sun.com/docs/books/tutorial/rmi/index.html"><font color="#0066a7">The Java&#8482; Tutorial Trail:RMI</font> </a></p>
        <li>
        <p>David Flanagan, Jim Farley, William Crawford and Kris Magnusson, 1999, ISBN 1-56592-483-5E, O'Reilly, <span><em>Java&#8482; Enterprise in a Nutshell</em></span></p>
        <li>
        <p>Ed Roman, Scott Ambler and Tyler Jewell 2002, ISBN 0-471-41711-4, John Wiley &amp;Sons, Inc., <span><em>Matering Enterprise JavaBeans&#8482;</em></span> , Second Edition</p>
        </li>
    </ul>
    </div>
<img src ="http://www.blogjava.net/site120/aggbug/159203.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-11-08 23:25 <a href="http://www.blogjava.net/site120/archive/2007/11/08/159203.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重新认识一下Java</title><link>http://www.blogjava.net/site120/archive/2007/11/08/159182.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Thu, 08 Nov 2007 14:43:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/11/08/159182.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/159182.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/11/08/159182.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/159182.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/159182.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp; Java是巨大的推动力量 ， Java已用动态的交互应用软件使Web栩栩如生。它使开发人员 具有&#8216;<span style="color: red">编写一次到处运行TM</span>&#8221;的巨大能力。而且，借助其JavaAPI 及其编程语言上的Java虚拟机，<span style="color: red">它已产生一种分布信息的崭新模式。 这种模式叫做Java企业计算</span>，正在帮助各企业以各种不同的方法取 得竞争优势。网管和控制已大大简化。软件分配基本上是免费的， 而且立即可实现。电子贸易已获得。占有成本大幅度降低。信息和 应用软件到处可存取。 </p>
<p>Java建立在简单的前提基础上，即<span style="color: red">所有微处理器都应讲同一种语言</span>——所有内部采用芯片的产品都应能一起工作，无缝而方便地 <strong style="color: red">共享信息</strong>。它已经改变企业和个人同Internet大交道的方式。现在， 它正在对消费类产品产生明显的影响，而且从总体上更加深刻地影 响企业计算。 </p>
<p><span style="color: red">借助Java，您可自由自在地使用您已拥有的硬件和软件</span>。这是因 为Java是独立于平台的。它还可使您超越企业计算，使应用软件在便 携式计算机、信息亭、电视、蜂窝电话和其他大量设备上运行。 全世界的公司都已发现Java数不胜数的用途。所有用途可从其无 可比拟的能力，即提高可靠性、安全性和简化各种不同计算产品和 环境的能力中受益非浅，而且节省的时间和费用十分可观。 </p>
<p><span style="color: red">Java无处不在</span>。它已拥有几百万个用户，其发展速度要快于在它 以前的其他任何一种计算机产品。它可位于任何地方，而且能到处运 行。Java正在迅速被用做传播信息的事实上标准，这是因为它既可给 企业，也可给最终用户带来似乎数不清的好处。 因此，请您仔细考察一下Java。它的优点是很容易发现的。 </p>
<p><br />
&#8220;Java正在进入企业、家庭和学校。 它正在象Internet本身一样成为普遍存在的技术。&#8221; <br />
Oracle 公司董事长和首席执行官 <br />
Larru Ellison </p>
<p><br />
&#8220;Java正在改变我们使用Internet的方法，改变我们 在公司内部存取信息的方法，甚至改变我们使用蜂窝 电话的方法。它正在从根本上改变制作信息、销售信息 和分配信息的方法。&#8221; <br />
EarthWeb公司董事长和首席执行官 <br />
Jack Hidary </p>
<p>&nbsp;</p>
<p>Java的来龙去脉 </p>
<p>Sun公司一小组工程师聚集在一起，认真思考日常生活中的 数字系统——因为烤面包机、恒温器、游戏机和其他无数设备 都包含越来越复杂的CPU——以及他们如何能使这些<span style="color: #ff0000">数字系统<strong>共享信息</strong></span>。 </p>
<p><br />
创造未来的计算 </p>
<p>制造产品的人当然全都从不同的方面来考虑其设计，视他们 所使用的硬件平台、操作系统和应用软件而定。但是，如果您要 使这些产品中的一些产品一起工作，那怎么办？安全性、可靠性 和网络问题又这么样呢？ </p>
<p>因此，Sun公司这些工程师把各种不同的产品折开来，然后又 把它们重新组装起来，其目标是要使这些不同的设备相互交谈。 他们把这些研究对象相互传来传去，并理解所有其他研究对象的 特性，以便使他们能更好地一起工作。这就把制造商的问题缩减 到最低程度，并使消费者能方便地进行集成。当传统的语言证明 是不适用时，工程师们就打算找到某种简单的现代新语言。于 是， Java应运而生。 </p>
<p>&nbsp; 人们很快发现，Java有可能超越工程师的想象。Java的魅力在 于它提供给开发人员和用户的简便性。开发人员拥有广大的用户基 础、平台独立性、降低的开发费用和始终如一的执行环境，而用户 则可 从生动的内容、即时软件和增大的安全性中受益。 但是，<span style="color: #ff0000">Java正是从置于World Wide Web那时起才真正起飞</span>。<br />
<br />
&nbsp; Java 使全世界大为震动，因为它使Web页面栩栩如生，而且不久变得很明 显，Java拥有大得多的潜力。人们之所以采纳Java，<span style="color: #ff0000">是因为它有独特 的能力来编制和部署能在任何一个网络、任何一个操作系统上运行的应用软件</span>。分配软件的时间和费用实际上已不复存在，使得各公司可 把更多的资源用来开发其产品。而且，某些工业专家认为，Java可能 会改变软件销售模式，从固定价格改变为按使用量收费，这样做更有 利可图，而且可阻止非法盗版。 <br />
<span style="color: #ff0000"><br />
<br />
&nbsp; Java是一种网络计算的通用开放标准平台</span>。这种平台可从电话一 直扩展到极端重要的应用，建立在您现有的硬件和软件体系结构基础 上，从而创造出一个全部联网的企业或者制造出超出的创新产品。 </p>
<p><br />
&#8220;由于Java具有可缩放性，因而我们可以把Java应用于小应用软件或大应用软件，把它芯片组以及大型计算机和服务器，并使它为各种不同的应用领域服务。&#8221; <br />
三菱公司系统营销副总裁 <br />
Steve Hester </p>
<p><br />
&#8220;借助Java，您可以用一种能最有效地使用的方式动态地分发和分配交互式商务应用软件一一在需要运行应用软件的地方， 在需要运行应用软件的时候。&#8221; <br />
Novell公司开发者服务部副总和总经理 <br />
Gary Mueller </p>
<p><br />
Java扎下根来 </p>
<p>在某种意义上，Java具体体现了Sun Microsystiems公司自其14年前创建以来所追述的目标。当时，它创造了&#8220;<span style="color: red">网络就是计算机</span>&#8221;这局名言。它市基于Web的新网络计算模式的完美平台，因为它建立在各个组织现有的硬件和软件体系结构基础上，能建立一个全部联网的企业。</p>
<p><span style="color: red"><br />
Java是一个完整而全面的解决方案Java远不止是一种编程语言，<span style="color: #000000">它是企业内外的完整计算环境，而且万事齐备，从开发工具、操作系统、服务器软件和瘦／肥客户机一直到网络管理工具、支持、培训、咨询和集成服务，一应俱全。Java使用起来非常简单，部分原因是Sun提供一种全面统一的解决方案.</span> </span></p>
<p>主要组成部分包括： <br />
*Java开发工具和服务：有助于简化开发Java应用软件的产品和服务 </p>
<p>*JavaOS：一种结构紧凑的操作系统，可使Java应用软件在网络计算机和蜂窝电话等设备上运行 </p>
<p>*Java虚拟机：一层软件，嵌入Windows、Macintosh和UNIX等计 算机操作系统，或在这些操作系统上运行，从而使计算机能 运行Java应用软件 </p>
<p>*Java API：标准软件界面，位于Java应用软件和数据库检索和 安全性等服务软件之间 </p>
<p>*Java芯片：一系列为Java优化的为处理器 </p>
<p>*Solstice WorkShop：Java启动的网络管理工具 </p>
<p>*Java培训：一个由教师指导和基于多媒体的完整课程，教会编 程员如何开发Java应用软件，包括一个用来验证熟练程度的 认证计划 </p>
<p>*JavaWorkShop支持：900号电话服务，可为Java WorkShop用户（仅限美国用户）立即提供按需支持 这些产品依靠由Sun的核心技术和服务提供的基础，包括： </p>
<p>*Solaris操作系统 <br />
*Sikstuce企业管理系统 <br />
*WorkShop开发者工具 <br />
*SunSpectrum支持服务 <br />
*Internet咨询和集成服务 <br />
*Java和Internet教育服务 <br />
*ultra工作站和Ultra Enterprise服务器;Netra服务器 </p>
<p>难怪大公司和日益增多的全球2000公司正在把Java计算用做系统以及其终产品的主要方面。 </p>
<p>&#8220;您不会把您自己锁住在任何一家公司的专有技术中。 开放意味着选择。而Java使您有选择余地。&#8221; </p>
<p>Oracle公司董事长和首席执行官 <br />
Larry Ellison</p>
<img src ="http://www.blogjava.net/site120/aggbug/159182.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-11-08 22:43 <a href="http://www.blogjava.net/site120/archive/2007/11/08/159182.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Java代码（非JSP及Action，Servlet，Controller）中获得WebRoot的物理路径</title><link>http://www.blogjava.net/site120/archive/2007/11/08/159178.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Thu, 08 Nov 2007 14:14:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/11/08/159178.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/159178.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/11/08/159178.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/159178.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/159178.html</trackback:ping><description><![CDATA[<p>在开发Web方面的应用时, 经常需要获取 服务器中当前WebRoot的物理路径<br />
<br />
如果是Servlet , Action , Controller, 或则Filter , Listener , 拦截器等相关类时， 我们只需要获得ServletContext， 然后通过ServletContext.getRealPath("/")来获取当前应用在服务器上的物理地址<br />
<br />
如果在类中取不到ServletContext时， 有两种方式可以做到<br />
<br />
1） 利用Java的类加载机制 调用 XXX.class.getClassLoader().getResource(""); 方法来获取到ClassPath , 然后处理获得WebRoot目录<br />
<br />
这种方式只能是该class在WebRoot/WEB-INF/classes下才能生效， 如果该class被打包到一个jar文件中， 则该方法失效。这时就应该用下面一种方式<br />
<br />
<br />
2） spring框架的思路, 在WEB-INF/web.xml中 ， 创建一个webAppRootKey的param, 指定一个值（默认为webapp.root）作为键值， 然后通过Listener , 或者Filter , 或者Servlet 执行String webAppRootKey = getServletContext().getRealPath("/"); 并将webAppRootKey对应的webapp.root 分别作为Key , Value写到System Properties系统属性中。之后在程序中通过System.getProperty("webapp.root")来获得WebRoot的物理路径<br />
<br />
&nbsp;根据第二种的思路，我们还可以再扩展一下。不过对于在部署在一台服务器中的应用来说，已经足够了。<br />
<br />
有更好的方法， 欢迎大家讨论</p>
<img src ="http://www.blogjava.net/site120/aggbug/159178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-11-08 22:14 <a href="http://www.blogjava.net/site120/archive/2007/11/08/159178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Aqua Data Studio 万能数据库客户端</title><link>http://www.blogjava.net/site120/archive/2007/11/08/159168.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Thu, 08 Nov 2007 13:29:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/11/08/159168.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/159168.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/11/08/159168.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/159168.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/159168.html</trackback:ping><description><![CDATA[<p>能够连接几乎所有的数据库，<br />
<br />
如：标准的JDBC/ODBC数据源， &nbsp;Mysql， SQLServer2000/2005 ， DB2 ， Oracle ， Sybase， PostgreSQL ， Informix 系列 , &#8230;&#8230;<br />
<br />
且功能强大， 自带JRE50MB左右， 去掉JRE&nbsp;&nbsp;20MB左右， 推荐使用!<br />
<br />
截图：<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/site120/aquadatastudio.JPG" border="0" /><br />
<br />
官方网站：<a href="http://www.aquafold.com/" target="_blank">http://www.aquafold.com/</a><br />
<br />
</p>
<img src ="http://www.blogjava.net/site120/aggbug/159168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-11-08 21:29 <a href="http://www.blogjava.net/site120/archive/2007/11/08/159168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jboss下Ejb简介</title><link>http://www.blogjava.net/site120/archive/2007/11/07/158704.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Tue, 06 Nov 2007 23:42:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/11/07/158704.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/158704.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/11/07/158704.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/158704.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/158704.html</trackback:ping><description><![CDATA[<p>JBoss是一个运行EJB的 J2EE应用服务器。它是开放源代码的项目，遵循最新的J2EE规范。从JBoss项目开始至今，它已经从一个EJB容器发展成为一个基于的J2EE的一 个web 操作系统（operating system for web），它体现了J2EE规范中最新的技术，并且它还在the JavaWorld Editors' Choice 2002评选中获得&#8220;最佳Java应用服务器&#8221;大奖。无论是学习还是应用，JBoss为我们提供了一个非常优秀的平台。有关JBoss的详细信息请参阅其 主页http://www.jboss.org。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 刚开始使用JBoss进行EJB开发时，由于可供参考的资源不是很多，所以有一个比较困难的起步阶段。JBoss的配置和使用没有提供图形向导界面，所以 开发部署EJB相对比较复杂。本文通过尽量具体的演示来对JBoss3.0下的EJB开发和部署的进行一个简单的介绍，从而使刚开始使用JBoss的用户 可以很快地进入到真正的J2EE应用开发中。</p>
<p>由于本文主要介绍JBoss3.0中不同类型EJB的配置和部署，不对基本的EJB开发做太多的描述，所以希望读者具有J2EE和EJB的经验。想要了解有关信息请查阅参考资料1。</p>
<p>2．JBoss3.0中基本的ejb配置和部署<br />
根 据J2EE规范的要求，一个基本的ejb jar包使用的描述文件是ejb-jar.xml。web应用的war包使用的是web.xml。企业应用的ear包使用的是 application.xml。这些配置文件都是中性的和平台无关的。同时应用服务器可以使用一些其他的配置文件用于描述特定服务器的相关信息。在 JBoss中这样的文件有jboss.xml，jboss-web.xml等。JBoss容器中这些文件不是必须的，如果提供了那么jboss.xml和 ejb-jar.xml放在同一目录下，jboss-web.xml和web.xml放在同一目录下。关于jboss.xml和jboss- web.xml的规范请参考JBoss安装目录下docs/dtd/目录下的对应的DTD文件。</p>
<p>2．1 JBoss中关于EJB客户端的配置：<br />
调 用EJB的客户端可以是JSP、Servlet或客户端应用程序。如果客户端和服务器不在同一个Java VM上，那么在客户端必须提供一个jndi.properties文件告诉客户端进行有关JNDI命名服务的信息，并且把这个文件所在目录设定到环境变量 classpath中。</p>
<p>以下是一个jndi.properties的样例：</p>
<p>java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory<br />
java.naming.provider.url=localhost:1099&nbsp; (服务器地址和端口号)<br />
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces<br />
通过这个文件和JBoss的一些客户端类库，就可以使用JBoss提供的EJB对象服务了。</p>
<p>2．2 JBoss中部署EJB：<br />
首先介绍JBoss容器中部署各类EJB对象的两种方法。下面的演示以Session Bean为例，客户端是一个本机上的web应用。这里不对演示程序进行具体介绍。</p>
<p>第一种方式：</p>
<p>把开发好的ejb jar包和web应用的war包公共放在deploy目录下。</p>
<p>演示1：不需要jboss.xml文件和其他任何特殊的设置。</p>
<p>ejb-jar.xml:</p>
<p>&nbsp;</p>
<p>&lt;ejb-jar&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;ejbtest&lt;/ejb-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&lt;/ejb-jar&gt;</p>
<p><br />
客户端：web应用中对web.xml不需要添加ejb信息，不需要jboss-web.xml文件。引用ejb对象的jsp文件如下：</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitialContext ctx = new InitialContext();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object objref&nbsp; = ctx.lookup("ejbtest");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //使用&lt;ejb-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beanHome=(zcxejb1Home)PortableRemoteObject.narrow(objref,ejbtestHome.class);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;</p>
<p>&nbsp;</p>
<p><br />
演示2：使用jboss.xml文件。</p>
<p>在 缺省情况下JBoss的JNDI服务将通过ejb-jar.xml中&lt;ejb-name&gt;XXX&lt;/ejb-name&gt;中的 XXX来使用EJB的home interface。但是如果有多个ejb对象在相同的ejb jar包中，在ejb-jar.xml中通过&lt;ejb-name&gt;XXX&lt;/ejb-name&gt;就可能不能很好的表示某一个 ejb对象，所以一般我们希望可以提供一些附加的信息，例如采用这样的格式"[应用名]/[bean名]"来引用一个EJB对象。这时JNDI服务就可能 不能正确地找到你的ejb对象，我们就需要使用jboss.xml文件，通过它实现jndi 名到ejb名的重定向。这个文件必须和ejb-jar.xml一起放到META-INFO目录下。</p>
<p>ejb-jar.xml:</p>
<p><br />
&lt;ejb-jar&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;ejbtest&lt;/ejb-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&lt;/ejb-jar&gt;</p>
<p><br />
jboss.xml:</p>
<p><br />
&lt;jboss&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;ejbtest&lt;/ejb-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;jndi-name&gt;example/ejbtest&lt;/jndi-name&gt;&lt;/jboss&gt;</p>
<p>&nbsp;</p>
<p><br />
客户端：需要使用新的jndi名进行ejb定位。</p>
<p><br />
&#183;&#183;&#183;&#183;&#183;&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitialContext ctx = new InitialContext();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object objref&nbsp; = ctx.lookup("example/ejbtest");&nbsp;&nbsp; //使用&lt;jndi-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beanHome=(zcxejb1Home)PortableRemoteObject.narrow(objref,ejbtestHome.class);&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p><br />
第二种方式： </p>
<p>把ejb 和web应用包装成一个企业应用包。部署ear时可以简单地把通过application.xml描述ejb jar包和web应用的war包，同样在web.war中不需要提供特殊的信息就可以和第一种方式一样使用ejb对象。客户端代码也不需要进行改动。这里 不再举例说明。</p>
<p>此外我们可以进行更进一步的部署，这时需要使用到web.xml和jboss-web.xml。jboss-web.xml是JBoss提供的一个针对web应用进行配置的文件。jboss-web.xml和web.xml一起放在web应用的WEB-INF目录下。</p>
<p>演示1：改动web.xml文件，添加&lt;ejb-ref&gt;标记，不使用jboss-web.xml文件。</p>
<p>（注意&lt;ejb-ref&gt;包括内部引用和外部引用。如果是同一个单元的可以通过&lt;ejb-link&gt;直接进行引用，而不用提供其他信息。）</p>
<p>web.xml:</p>
<p><br />
&#183;&#183;&#183;&#183;&#183;&#183;&lt;ejb-ref&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref-name&gt;ejb/ejbtest&lt;/ejb-ref-name&gt;&nbsp; &lt;!--采用sun推荐的命名方式--&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref-type&gt;Session&lt;/ejb-ref-type&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;home&gt;org.zcx.test.zcxejb1Home&lt;/home&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;remote&gt;org.zcx.test.zcxejb1&lt;/remote&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-link&gt;ejbtest&lt;/ejb-link&gt;&nbsp;&nbsp;&nbsp; &lt;!--必须和被应用的ejb-name匹配--&gt;&lt;/ejb-ref&gt;&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p><br />
客户端：由于在web.xml中引入ejb引用描述这时ejb定位发生了变化：</p>
<p><br />
&#183;&#183;&#183;&#183;&#183;&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitialContext ctx = new InitialContext();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object objref&nbsp; = ctx.lookup("java:comp/env/ ejb/ejbtest "); //使用java:comp/env命名空间&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beanHome=(zcxejb1Home)PortableRemoteObject.narrow(objref,ejbtestHome.class);&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p>&nbsp;</p>
<p><br />
演示2：联合使用web.xml和jboss-web.xml</p>
<p>web.xml</p>
<p><br />
&#183;&#183;&#183;&#183;&#183;&#183;&lt;ejb-ref&gt;&lt;ejb-ref-name&gt;ejb/ejbtest&lt;/ejb-ref-name&gt;&nbsp; &lt;!--采用sun推荐的命名方式--&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-ref-type&gt;Session&lt;/ejb-ref-type&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;home&gt;org.zcx.test.zcxejb1Home&lt;/home&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;remote&gt;org.zcx.test.zcxejb1&lt;/remote&gt;&lt;/ejb-ref&gt;&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p><br />
jboss-web.xml</p>
<p><br />
&lt;ejb-ref&gt;&lt;ejb-ref-name&gt; ejb/ejbtest &lt;/ejb-ref-name&gt;&lt;jndi-name&gt; example/ejbtest &lt;/jndi-name&gt; &lt;!-- 这里对应ejb对象的jndi名--&gt;&lt;/ejb-ref&gt;</p>
<p><br />
客户端：</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nitialContext ctx = new InitialContext();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object objref&nbsp; = ctx.lookup("java:comp/env/ ejb/ejbtest ");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beanHome=(zcxejb1Home)PortableRemoteObject.narrow(objref,ejbtestHome.class);</p>
<p>&nbsp;</p>
<p><br />
以上的所有演示说明了ejb-jar.xml、jboss.xml、web.xml、jboss-web.xml之间的基本关系和它们的使用方式。它们是部署各类ejb对象的关键文件。接下来介绍针对不同类型的ejb对象所需要的特殊配置。</p>
<p>3．JBoss3.0中对于CMP2.0 Entity Bean的有关配置<br />
JBoss3.0 中JBossCMP引擎实现了EJB2.0 CMP2.0规范。JBoss3.0以前的版本CMP的引擎是Jaws，它通过standardjaws.xml和jaws.xml进行有关的配置。在新 的JBossCMP引擎中Jboss3.0通过standardjbosscmp-jdbc.xml和josscmp-jdbc.xml来配置 Entity Bean。JBoss3.0首先处理standardjbosscmp-jdbc.xml然后根据ejb jar中是否提供jbosscmp-jdbc.xml来做进一步处理。通过standardjbosscmp-jdbc.xml和jbosscmp- jdbc.xml可以为entity bean的部署提供如下的功能有：</p>
<p>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定所使用的数据源和对应的类型映射 </p>
<p>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定一些引擎关心的属性</p>
<p>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定引擎如何创建和管理数据库表的原则</p>
<p>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 描述finder和ejbSelect方法</p>
<p>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定属性和字段的类型映射 </p>
<p>这 里主要根据standardjbosscmp-jdbc.xml/jbosscmp-jdbc.xml介绍CMP2.0的配置方法。JBoss中原有的 Jaws引擎的配置方法和新的JBossCMP的配置方法类似。这些文件的具体的信息可以参考JBoss安装路径下\docs\dtd中对应的DTD文 件。</p>
<p>3．1增加新的数据源<br />
JBoss自带的数据库是Hypersonic数据库，我们可以增加一些新的数据源。具 体的步骤很简单，参照Jboss安装目录下\docs\examples\jca中的*-service.xml文件可以增加找到对应类型的数据库配置样 本文件。以mysql-service.xml文件为例，它可以配置一个MySQL数据库作为Entity Bean的数据源。以下演示创建一个名为MySQLDS的MySQL数据源。</p>
<p>图一是配置好的mysql-service.xml文件的一段代码样本，通过属性设置可以定制数据源的名称和有关连接的其他属性。注意该文件中所有name属性必须保持一致。</p>
<p><br />
图一 mysql-servic.xml的样本代码</p>
<p>在配置好这个文件后，把它部署在JBoss的deploy目录下，把对应的jdbc驱动也放在lib目录下。重新启动Jboss就会加载这个新的数据源。</p>
<p>3．2 Entity Bean 对数据源的使用<br />
第一种方式：</p>
<p>直 接改动standardjbosscmp-jdbc.xml。把原有的数据源java:/DefautlDS屏蔽掉使用新的数据源java: /MySQLDS。（Java前缀是必须的。）不需在其他地方作改动。JBoss会实现新的数据源做为缺省的数据源。图二是一个配置好的文件片断。</p>
<p><br />
图二 standardjbosscmp-jdbc.xml的样本代码</p>
<p>第二种方式：</p>
<p>由 于有可能不同的Entity Bean使用不同的数据源，而不是都使用同样的缺省配置，所以必须为单独的Entity Bean提供定制数据源信息的支持。这时不需要改动standardjbosscmp-jdbc.xml文件，可以通过在Entity Bean的jar包中META-INFO目录下添加新的部署文件jbosscmp-jdbc.xml来完成。通过这个文件可以描述特定的Entity Bean的关于数据源的配置信息。图三是一个配置好的文件片断。</p>
<p><br />
图三 jbosscmp-jdbc.xml的样本代码</p>
<p>4．JBoss3.0中对于Message Driven Bean的配置<br />
在JBoss 中开发MDB需要使用JMS功能。JMS是Sun公司开发的面向消息的中间件API。它的主要目的是创造一种统一的面向消息编程的JavaAPI，从而避 免使用提供商特定的API。现在有几种不同的JMS系统可供使用。JBoss3.0中提供的是JBossMQ。</p>
<p>4．1 JBoss3.0中配置JMS服务<br />
在JBoss3.0 中与JMS服务相关的配置文件包括两个文件：jbossMQ-service.xml和jbossMQ-destinations- service.xml。jbossMQ-service.xml配置了jbossMQ服务中的核心对象信息。一般我们不需要处理这个配置文件。 jbossMQ-destinations-service.xml用于定义具体应用所需的目的地信息。通过编辑它我们可以创建新的Topic和 Queue用于具体的JMS应用的目的地。在JBoss中创建应用特定的Topic和Queues的步骤比较简单，参照jbossMQ- destinations-service.xml文件格式在该文件中添加自己应用程序所需的Topic名为myTestAppTopic和Queue名 为myTestAppQueue。如图四所示。</p>
<p><br />
图四&nbsp; jbossMQ-destinations-service.xml的样本代码</p>
<p>4．2 JBoss3.0中EJB使用JMS服务的配置<br />
在开发MDB 时要在部署文件中指定所使用的JMS服务中的目的地信息。JBoss中通过ejb-jar.xml和jboss.xml共同说明。在jboss.xml中通过&lt;destination-jndi-name&gt;标记描述所使用的目的地信息。</p>
<p>Ejb-jar.xml</p>
<p><br />
&lt;message-driven&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;HelloTopicMDB&lt;/ejb-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-class&gt;org.zcx.test.HelloMDB&lt;/ejb-class&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;message-selector&gt;&lt;/message-selector&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;transaction-type&gt;Container&lt;/transaction-type&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;message-driven-destination&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;destination-type&gt;javax.jms.Topic&lt;/destination-type&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;subscription-durability&gt;NonDurable&lt;/subscription-durability&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/message-driven-destination&gt;&lt;/message-driven&gt;</p>
<p><br />
jboss.xml</p>
<p><br />
&nbsp; &lt;message-driven&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ejb-name&gt;HelloTopicMDB&lt;/ejb-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;configuration-name&gt;Standard Message Driven Bean&lt;/configuration-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;destination-jndi-name&gt;topic/myAppTestTopic&lt;/destination-jndi-name&gt;&nbsp;&nbsp;&nbsp; &lt;/message-driven&gt;</p>
<p><br />
客户端：</p>
<p><br />
&#183;&#183;&#183;&#183;&#183;&#183;Context context = new InitialContext();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Get the connection factory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create the connection&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create the session&#183;&#183;&#183;&#183;&#183;&#183;// Look up the destination&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; topic = (Topic)context.lookup("topic/myTestAppTopic");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create a publisher// Publish the message&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p><br />
5．JBoss3.0中EJB使用JavaMail服务的配置。<br />
由于JBoss提供了JavaMail服务的实现，所以在JBoss中使用JavaMail是非常方便地。它所需要配置的是mail.service文件。这个文件非常地简单不用多介绍。按照mail.service文件的的注释就可以顺利地完成配置。</p>
<p>图五是使用JavaMail服务的一个sessionBean的代码片断</p>
<p><br />
图五&nbsp; 使用javamail的样本代码</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>以 上通过例子简单的介绍了JBoss3.0中Session Bean、Entity Bean 和Message Drive Bean 最基本的配置和部署方法，通过这些介绍现在已经可以在JBoss中进行基本的EJB应用的开发了。本文中对于EJB应用中比较复杂的一些配置像权限设置、 资源管理和CMP2.0中的众多配置等都没有涉及到，希望大家可以在不断的实践和交流中更好地掌握JBoss的使用和配置。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>参考资料：<br />
1．&nbsp; http://java.sun.com/j2ee/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; J2EE 和 EJB</p>
<p>2．&nbsp; http://www.jboss.org/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JBoss项目主页和在线手册</p>
<p>3．&nbsp; 《JBoss3.0 Quick Start》&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the JBoss Group</p>
<p>4．&nbsp; 《Mastering Enterprise Java Beans, 2nd Edition》 Ed Roman, Scott Ambler, and Tyler Jewel. <br />
</p>
<img src ="http://www.blogjava.net/site120/aggbug/158704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-11-07 07:42 <a href="http://www.blogjava.net/site120/archive/2007/11/07/158704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBoss简介</title><link>http://www.blogjava.net/site120/archive/2007/11/06/158675.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Tue, 06 Nov 2007 14:34:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/11/06/158675.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/158675.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/11/06/158675.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/158675.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/158675.html</trackback:ping><description><![CDATA[<br />
<strong>解释1:</strong><br />
<br />
　Jboss是 web服务器的一种，主要做ejb容器，和tomcat集成就可以jsp,servlet,ejb通吃了 <br />
　Jboss有两种版本，一种是独立的，一种是和tomcat集成的，当然都是免费的啦 <br />
　EJB(enterprise javabean)，他不是javabean简单的升级，而是一些提供分布式访问的类 <br />
　包括实体bean,会话bean,消息驱动bean <br />
--------------------------------------------------------------- <br />
<strong>JBoss简介 <br />
</strong>　JBoss是一个运行EJB的J2EE应用服务器。它是开放源代码的项目，遵循最新的J2EE规范。从JBoss项目开始至今，它已经从一个EJB容器发展成为一个基于的J2EE的一个web 操作系统（operating system for web），它体现了J2EE规范中最新的技术，并且它还在the JavaWorld Editors' Choice 2002评选中获得&#8220;最佳Java应用服务器&#8221;大奖。无论是学习还是应用，JBoss为我们提供了一个非常优秀的平台。有关JBoss的详细信息请参阅其主页http://www.jboss.org。 <br />
<br />
　刚开始使用JBoss进行EJB开发时，由于可供参考的资源不是很多，所以有一个比较困难的起步阶段。JBoss的配置和使用没有提供图形向导界面，所以开发部署EJB相对比较复杂。本文通过尽量具体的演示来对JBoss3.0下的EJB开发和部署的进行一个简单的介绍，从而使刚开始使用JBoss的用户可以很快地进入到真正的J2EE应用开发中。 <br />
<br />
　Enterprise JavaBean (EJB)规范定义了开发和部署基于事务性、分布式对象应用程序的服务器端软件组件的体系结构。企业组织可以构建它们自己的组件，或从第三方供应商购买组件。这些服务器端组件称作 Enterprise Bean，它们是 Enterprise JavaBean 容器中驻留的分布式对象，为分布在网络中的客户机提供远程服务。<br />
<br />
<strong>解释2:</strong><br />
<br />
　JBoss是一个开源的符合J2EE规范的应用服务器，作为J2EE规范的补充，Jboss中引入了AOP框架，为普通Java类提供了J2EE服务，而无需遵循EJB规范。Jboss通过类载入时，使用Javassist对字节码操作实现动态AOP框架，Javassist是一个开源的编辑字节码的类库。
<p>　Jboss中参考，切入点与方面也由普通Java对象实现，并使用XML文件配置。Jboss的连接点模型与AspectJ略有不同，提供了一系列预定义的切入点，包括类匹配，方法调用，构造器调用，域访问，特定的调用与被调用关系。通过这些切入点的逻辑运算，可以实现更为复杂的切入点。方面为Java类，参考是其中的一个方法，方面中不含切入点，方面主要为各种拦截器（Interceptor），拦截器即为只含一个参考的方面，单一连接点上可由多个拦截器形成拦截器链，拦截器执行额外的操作。对方法的拦截由Advisor类管理，在连接点依次调用拦截器，并最终调用被逻辑的方法。而关于切入点，参考已及方面的信息由AspectManager管理。此外，Jboss提供对元数据的支持，用于为类，方法，构造器以及域添加额外的属性，并可在运行期访问。</p>
<p>　为实现拦截，Jboss需要修改类的字节码，大致过程如下。</p>
<p>　XML配置文件中关于切入点，拦截器，元数据以及混合类的信息在应用程序部署时被读入、解析，并生成相应的对象，这些信息与实例化的对象由AspectManager管理。在需要混入方面代码的类载入时，AspectManager将创建Advisor类，将方面相关信息传递给它，并对类的字节码进行修改，之后将修改过的字节码交给类载入器完成类的装载。字节码的修改主要是对被载入的类添加一系列方法用于代理那些匹配连接点的方法调用，构造器调用，域访问以及方法导入，转为对Advisor类相应方法的调用。类中各方法将重命名，保留原方法体，并添加一个与原方法同名的方法，在这个方法中调用那些代理方法，用来将调用代理给Advisor类，或调用重命名的原方法。对于域访问，分别添加两个方法，对应于读与写操作，将域访问代理至Advisor类，在访问这个域的类中，则需将对域的访问转换为对上述方法的调用。对于构造器调用，则添加一个方法，将调用代理至Advisor类，并对构造对象的类的构造代码作相应转换。对于导入，被导入的类中将添加一个混合类实现的引用，并添加混合类接口中的方法，将对混合类方法的调用代理至Advisor类，并最终调用混合类的实现。相关类载入后，初始化Advisor类，填入拦截器链，以完成整个处理过程。</p>
<p><strong>一、JBoss简介</strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 近年来，在J2EE应用服务器领域，JBoss是发展最为迅速的应用服务器。JBoss是免费的，开放源代码J2EE的实现，它通过LGPL许可证进行发布,这使得JBoss广为流行。Boss是一个运行EJB的J2EE应用服务器，例如：数据库访问JDBC、交易(JTA/JTS)、消息机制(JTS)、命名机制(JNDI)和管理支持(JMX)。它是开放源代码的项目，遵循最新的J2EE规范。目前的JBoss发布版2.2.4实现了EJB 1.1和部分EJB 2.0的标准、JMS 1.0.1、Servlet 2.2、JSP 1.1、JMX 1.0、JNDI 1.0、JDBC 1.2和2.0扩充(支持连接池 (Connection Polling))、JavaMail/JAF、JTA 1.0和JAAS1.0标准，JBoss是100%纯Java实现能运行于任何平台。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从JBoss项目开始至今，它已经从一个EJB容器发展成为一个基于的J2EE的一个web 操作系统（operating system for web），它体现了J2EE规范中最新的技术，并且它还在the JavaWorld Editors' Choice 2002评选中获得&#8220;最佳Java应用服务器&#8221;大奖。无论是学习还是应用，JBoss为我们提供了一个非常优秀的平台。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<strong> 另外，JBoss应用服务器还具有许多优秀的特质:</strong> </p>
<p>它将具有革命性的JMX微内核服务作为其总线结构； <br />
它本身就是面向服务的架构（Service-Oriented Architecture，SOA）； <br />
它还具有统一的类装载器，从而能够实现应用的热部署和热卸载能力。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因此，它是高度模块化的和松耦合的。JBoss用户的积极反馈告诉我们，JBoss应用服务器是健壮的、高质量的，而且还具有良好的性能。 </p>
<p><strong>二、JBoss的发展</strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为满足企业级市场日益增长的需求，JBoss公司从2003年开始就推出了24*7、专业级产品支持服务。同时，为拓展JBoss的企业级市场， JBoss公司还签订了许多渠道合作伙伴。在2004年6月，JBoss公司宣布，JBoss应用服务器通过了Sun公司的J2EE认证。 这是JBoss应用服务器发展史上至今为止最重要的里程碑。与此同时，JBoss一直在紧跟最新的J2EE规范， 而且在某些技术领域引领J2EE规范的开发。因此，无论在商业领域，还是在开源社区， JBoss成为了第一个通过J2EE 1.4认证的主流应用服务器。现在，JBoss应用服务器已经真正发展成具有企业强度（即，支持关键级任务的应用）的应用服务器。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 近年来，Hibernate已经成为了事实上的持久化引擎。JBoss公司致力于将自身发展成为开源项目的社区，最新版的JBoss应用服务器已经将Hibernate集成为JMXMBean服务。这使得用户能够在应用服务器环境中直接使用Hibernate，而不管它是否处于J2EE上下文中。在最新版的JBoss应用服务器中，用户能够直接通过JMXMBean服务访问到JBossCache提供的服务。下一代的JBoss应用服务器（暂定名为，JBoss5.0）将提供大量的新功能。除了支持最新的EJB 3.0规范外，新版的JBoss AOP将同它正式发布。同时，JBoss开发团队还计划开发新的微内核层，即独立于JMX，使得它能够独立使用。 </p>
<p><br />
<strong>三、JBoss的服务器架构概述</strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JBoss的构架和其他J2EE应用服务器的构架有着巨大的不同。JBoss的模块架构是建立在JMX底层上的，下图展现了JBoss主要组件和JMX的联系。 </p>
<p align="center"><img src="http://java.chinaitlab.com/UploadFiles_8734/200706/20070615171106568.jpg" border="0"  alt="" /></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>JMX - 层次</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp; JMX是一个可复用框架，它为远程(Remote)和本地(Local)管理工具扩展了应用。它的架构是层式架构。他们是实现层(instrumentation layer)、代理层(agent layer)和发布层(distribution layer)。其中，发布层还在等待未来的标准化。简要的表述是，用户使用管理Bean，MBean来提供获得相应资源的实现方法。实现层实现相关的特性资源并将它发布于JMX相关应用中，它的代理层控制和发布相应的注册在MBeanServer代理上的管理资源。 </p>
<p align="center"><img src="http://java.chinaitlab.com/UploadFiles_8734/200706/20070615171107439.jpg" border="0"  alt="" /></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>JBoss主要模块<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp; 主要的JBoss模块是在MeanServer上的可管理MBean。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 1.JBoss EJB容器是JBoss服务器的核心实现。它有两个特性，第一是在运行期产生EJB 对象的Stub和Skeleton类，第二是支持热部署。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 2.JBossNS是JBoss命名服务用来定位对象和资源。它实现了JNDI J2EE规范.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 3.JBossTX 是由JTA/JTS支持的交易管理控制. </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 4.部署服务支持EJB(jar)、Web应用文档(war)和企业级应用文档(ears)的部署。它会时刻关心J2EE应用的URL情况，一旦它们被改变或出现的时候将自动部署。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 5.JBossMQ使Java 消息规范(JMS)的实现。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 6.JBossSX支持基于JAAS的或不支持JAAS机制的安全实现。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 7.JBossCX实现了部分JCA的功能。JCA制订了J2EE应用组件如何访问基于连接的资源。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 8.Web服务器支持Web容器和Servlet引擎。JBoss 2.4.x版本支持Tomcat 4.0.1，Tomcat 3.23和Jetty 3.x服务.</p>
<p><br />
<strong>四、JBoss架构设计中的两个重要的特性</strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一是使用JMX作为一个软件总线垂直的贯穿其所有的服务，通过将新的服务组件遵循JMX规范挂接上"总线"，使得系统扩展现有的服务变得容易。可插入式框架被广泛的运用于服务的实现。开发者可以选择他们需要的服务并编写他们所需要的相应实现，通过定义在部署描述文件中，让JBoss服务器知道。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 第二是容器被设计成为动态代理机制，这样使容器的实现变得简单和使开发者避免费劲的将jar文件进行预编译以获得stub和skeleton代码。但是这样做潜在的问题是性能和可测性，因为我们知道java反射机制会引起性能的损失。JBoss中存在着相应的优化方案并且在将来的研究中我们会论述该优化方法在什么时候工作并且是如何工作的</p>
<br />
摘自：<font style="font-size: 12pt" color="#1e8dc5"><strong><a href="http://blog.chinaunix.net/u/19919/showart_346600.html" target="_blank"><font style="font-size: 12pt" color="#1e8dc5"><strong>厚积而薄发</strong></font></a></strong></font>
 <img src ="http://www.blogjava.net/site120/aggbug/158675.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-11-06 22:34 <a href="http://www.blogjava.net/site120/archive/2007/11/06/158675.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MyEclipse 6.0.1 6.0GA 6.0M1 5.5GA 5.1.1GA 注册码</title><link>http://www.blogjava.net/site120/archive/2007/10/28/156445.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Sun, 28 Oct 2007 02:03:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/10/28/156445.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/156445.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/10/28/156445.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/156445.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/156445.html</trackback:ping><description><![CDATA[<p>MyEclipse 6.0.1 注册码</p>
<pre class="bb-code-block">Subscriber: administrator
Subscription Code: nLR7ZL-655342-54657656405281154</pre>
<p>注册后：</p>
<pre class="bb-code-block">Subscriber: administrator
Product ID: E2MY (MyEclipse Standard Subscription)
License version: 1.0
Full Maintenance Included
Subscription expiration date (YYYYMMDD): 20091021
Number of licenses: 897
</pre>
<p>&nbsp;</p>
<p>下面把 6.0GA / M1 和 5.5GA 版本的&#8220;注册信息&#8221;&#8220;注册码&#8221;&#8220;破解&#8221;给大家：</p>
<pre class="bb-code-block">Subscriber:
Subscriber Code: jLR8ZC-655355-5450765457039125
或者
Subscriber:
Subscriber Code: jLR7ZL-655355-5450755330522962</pre>
<p>适用于早期的 5.5 M2 版本的：</p>
<pre class="bb-code-block">Subscriber:
Subscriber Code: jLR8ZC-956-55-5467865833584547</pre>
<p>适用于早期的 5.1.1 GA 和 5.5 M1 版本的：</p>
<pre class="bb-code-block">Subscriber:
Subscriber Code: jLR8ZC-444-55-4467865481680090</pre>
<p>注册成功后会发现：</p>
<pre class="bb-code-block">Subscriber:
Product ID: E3MP (MyEclipse Professional Subscription)
License version: x.x
Full Maintenance Included
Subscription expiration date (YYYYMMDD): 20090520
Number of licenses: 800</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/site120/aggbug/156445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-10-28 10:03 <a href="http://www.blogjava.net/site120/archive/2007/10/28/156445.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WebWork + Spring + Hibernate 快速上手教程</title><link>http://www.blogjava.net/site120/archive/2007/08/27/139903.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Mon, 27 Aug 2007 06:11:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/08/27/139903.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/139903.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/08/27/139903.html#Feedback</comments><slash:comments>50</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/139903.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/139903.html</trackback:ping><description><![CDATA[<p>非常不错的教程<br />
如果有要的留下Email！<br />
<br />
在看到的第一时间内回复</p>
  <img src ="http://www.blogjava.net/site120/aggbug/139903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-08-27 14:11 <a href="http://www.blogjava.net/site120/archive/2007/08/27/139903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AntLr</title><link>http://www.blogjava.net/site120/archive/2007/02/02/92713.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Thu, 01 Feb 2007 17:01:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/02/02/92713.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/92713.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/02/02/92713.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/92713.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/92713.html</trackback:ping><description><![CDATA[
		<p>一个非常不错的开源语言解析工具, Hibernate 就是利用此对HQL语言进行分析的<br />有机会熟悉一下. 其里面的ATS(语法抽象树) 用来描述一种业务规则. 利用它我们甚至可以开始出自己的编程语言.</p>
<img src ="http://www.blogjava.net/site120/aggbug/92713.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-02-02 01:01 <a href="http://www.blogjava.net/site120/archive/2007/02/02/92713.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Jakarta Commons组件重写Object 对象的equals , hashCode方法</title><link>http://www.blogjava.net/site120/archive/2007/02/02/97395.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Thu, 01 Feb 2007 16:27:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/02/02/97395.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/97395.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/02/02/97395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/97395.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/97395.html</trackback:ping><description><![CDATA[
		<p>
		</p>
		<p>对于一些编程当中的机制,有的是需要我们重写equals,hashCode方法的.<br />比如:<br />   1) <strong>Map&lt;Key , Value&gt;类型中的Key, 首先它必须是对象, 其次它得要重构方法equals , hashCode , 以此来查找键,并确定两键值是否相同<br /><br /></strong>  <strong> 2) 在Set&lt;Object&gt; 集合中, set容器里面的一个值(这里面判断两个对象是否是相同的值也是依靠equals与hashCode的)只能存放一次, 那它也要求重构equals , hashCode方法<br /><br /></strong>   <strong>3) 在Hibernate的映射文件里面, 其中的ID对象如果是复合主键,则也同样要求重构equlas, hashCode方法<br /></strong>...<br /><br />重写这两个方法一般都比较烦琐, 下面我们可以利用apache 的commons组件来帮助我们完成<br /><br />-----------------------------------------------以下转自其它网站-----------------------------------------------------<br />Jakarta-Commons的org.apache.commons.lang.builder包中，完全由一些类组成，他们专门设计为协助实现，继承了java.lang.Object的类的一些基本方法。比如：equals() , hashCode() , and toString()。他们被称为建造器，是因为他们提供了一组简便易用的API为了达到实现这些方法的效果。</p>
		<div>The EqualsBuilder</div>
		<div>首先讨论的是EqualsBuilder。这个类，可能你已经猜到了，是帮助重写object 的equals方法的。</div>
		<div>让我们先写一个class：</div>
		<div>
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #008080">1</span>
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">class</span>
						<span style="COLOR: #000000"> MyClass <br /></span>
						<span style="COLOR: #008080">2</span>
						<span style="COLOR: #000000">
								<img id="Codehighlighter1_22_101_Open_Image" onclick="this.style.display='none'; Codehighlighter1_22_101_Open_Text.style.display='none'; Codehighlighter1_22_101_Closed_Image.style.display='inline'; Codehighlighter1_22_101_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
								<img id="Codehighlighter1_22_101_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_101_Closed_Text.style.display='none'; Codehighlighter1_22_101_Open_Image.style.display='inline'; Codehighlighter1_22_101_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />
						</span>
						<span id="Codehighlighter1_22_101_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_22_101_Open_Text">
								<span style="COLOR: #000000">{<br /></span>
								<span style="COLOR: #008080">3</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />  </span>
								<span style="COLOR: #0000ff">private</span>
								<span style="COLOR: #000000"> String field1;<br /></span>
								<span style="COLOR: #008080">4</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />  </span>
								<span style="COLOR: #0000ff">private</span>
								<span style="COLOR: #000000"> String field2;<br /></span>
								<span style="COLOR: #008080">5</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />  </span>
								<span style="COLOR: #0000ff">private</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">double</span>
								<span style="COLOR: #000000">[] field3;<br /></span>
								<span style="COLOR: #008080">6</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
						</span>
						<span style="COLOR: #000000">
								<br />
						</span>
						<span style="COLOR: #008080">7</span>
						<span style="COLOR: #000000">
								<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
								<br />
						</span>
						<span style="COLOR: #008080">8</span>
						<span style="COLOR: #000000">
								<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
						</span>
				</div>
				<br />下面我们将使用EqualsBuilder去处理两个实现了相同类的object是否相同的方法。</div>
		<div>
				<br />
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #008080"> 1</span>
						<img id="Codehighlighter1_33_366_Open_Image" onclick="this.style.display='none'; Codehighlighter1_33_366_Open_Text.style.display='none'; Codehighlighter1_33_366_Closed_Image.style.display='inline'; Codehighlighter1_33_366_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
						<img id="Codehighlighter1_33_366_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_33_366_Closed_Text.style.display='none'; Codehighlighter1_33_366_Open_Image.style.display='inline'; Codehighlighter1_33_366_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">boolean</span>
						<span style="COLOR: #000000"> equals(Object o) </span>
						<span id="Codehighlighter1_33_366_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_33_366_Open_Text">
								<span style="COLOR: #000000">{<br /></span>
								<span style="COLOR: #008080"> 2</span>
								<span style="COLOR: #000000">
										<img id="Codehighlighter1_69_92_Open_Image" onclick="this.style.display='none'; Codehighlighter1_69_92_Open_Text.style.display='none'; Codehighlighter1_69_92_Closed_Image.style.display='inline'; Codehighlighter1_69_92_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
										<img id="Codehighlighter1_69_92_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_69_92_Closed_Text.style.display='none'; Codehighlighter1_69_92_Open_Image.style.display='inline'; Codehighlighter1_69_92_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />   </span>
								<span style="COLOR: #0000ff">if</span>
								<span style="COLOR: #000000"> ( </span>
								<span style="COLOR: #000000">!</span>
								<span style="COLOR: #000000">(o </span>
								<span style="COLOR: #0000ff">instanceof</span>
								<span style="COLOR: #000000"> MyClass) ) </span>
								<span id="Codehighlighter1_69_92_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
										<img src="http://www.blogjava.net/images/dot.gif" />
								</span>
								<span id="Codehighlighter1_69_92_Open_Text">
										<span style="COLOR: #000000">{<br /></span>
										<span style="COLOR: #008080"> 3</span>
										<span style="COLOR: #000000">
												<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">return</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">false</span>
										<span style="COLOR: #000000">;<br /></span>
										<span style="COLOR: #008080"> 4</span>
										<span style="COLOR: #000000">
												<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />   }</span>
								</span>
								<span style="COLOR: #000000">
										<br />
								</span>
								<span style="COLOR: #008080"> 5</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />  MyClass rhs </span>
								<span style="COLOR: #000000">=</span>
								<span style="COLOR: #000000"> (MyClass) o;<br /></span>
								<span style="COLOR: #008080"> 6</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />  </span>
								<span style="COLOR: #0000ff">return</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">new</span>
								<span style="COLOR: #000000"> EqualsBuilder()<br /></span>
								<span style="COLOR: #008080"> 7</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                 .appendSuper(</span>
								<span style="COLOR: #0000ff">super</span>
								<span style="COLOR: #000000">.equals(o))<br /></span>
								<span style="COLOR: #008080"> 8</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                 .append(field1, rhs.field1)<br /></span>
								<span style="COLOR: #008080"> 9</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                 .append(field2, rhs.field2)<br /></span>
								<span style="COLOR: #008080">10</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                 .append(field3, rhs.field3)<br /></span>
								<span style="COLOR: #008080">11</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                 .isEquals();<br /></span>
								<span style="COLOR: #008080">12</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />  }</span>
						</span>
				</div>
		</div>
		<div>
				<br />这个特别的建造器并没有彻底的从这种标准的实现中节省时间，除了自动的处理了数组。</div>
		<div>另外，你也可以选择使用反射机制的静态方法：</div>
		<div>
				<br />
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #008080">1</span>
						<img id="Codehighlighter1_32_86_Open_Image" onclick="this.style.display='none'; Codehighlighter1_32_86_Open_Text.style.display='none'; Codehighlighter1_32_86_Closed_Image.style.display='inline'; Codehighlighter1_32_86_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
						<img id="Codehighlighter1_32_86_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_32_86_Closed_Text.style.display='none'; Codehighlighter1_32_86_Open_Image.style.display='inline'; Codehighlighter1_32_86_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">boolean</span>
						<span style="COLOR: #000000"> equals(Object o) </span>
						<span id="Codehighlighter1_32_86_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_32_86_Open_Text">
								<span style="COLOR: #000000">{<br /></span>
								<span style="COLOR: #008080">2</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   </span>
								<span style="COLOR: #0000ff">return</span>
								<span style="COLOR: #000000"> EqualsBuilder.reflectionEquals(</span>
								<span style="COLOR: #0000ff">this</span>
								<span style="COLOR: #000000">, o);<br /></span>
								<span style="COLOR: #008080">3</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /> }</span>
						</span>
						<span style="COLOR: #000000">
								<br />
						</span>
						<span style="COLOR: #008080">4</span>
						<span style="COLOR: #000000">
								<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
						</span>
				</div>
				<br />这种方法实现equals算法，有两个缺点。</div>
		<div>1、因为使用了反射机制，所以速度可能会比较慢。</div>
		<div>2、在安全-受限的JVMs中，在使用中的字段修改将会导致这个方法失效。</div>
		<div>不过，对于快速开发，这是个很好的工具。</div>
		<div>
		</div>
		<div>The HashCodeBuilder </div>
		<div>是一个节省时间并能很好地避免错误的建造器。下面将实现一个hashcode算法。</div>
		<div>
				<br />
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #008080">1</span>
						<img id="Codehighlighter1_22_161_Open_Image" onclick="this.style.display='none'; Codehighlighter1_22_161_Open_Text.style.display='none'; Codehighlighter1_22_161_Closed_Image.style.display='inline'; Codehighlighter1_22_161_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
						<img id="Codehighlighter1_22_161_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_161_Closed_Text.style.display='none'; Codehighlighter1_22_161_Open_Image.style.display='inline'; Codehighlighter1_22_161_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000"> hashCode() </span>
						<span id="Codehighlighter1_22_161_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_22_161_Open_Text">
								<span style="COLOR: #000000">{<br /></span>
								<span style="COLOR: #008080">2</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
								<span style="COLOR: #0000ff">return</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">new</span>
								<span style="COLOR: #000000"> HashCodeBuilder(</span>
								<span style="COLOR: #000000">61</span>
								<span style="COLOR: #000000">, </span>
								<span style="COLOR: #000000">15</span>
								<span style="COLOR: #000000">)<br /></span>
								<span style="COLOR: #008080">3</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />  .appendSuper(</span>
								<span style="COLOR: #0000ff">super</span>
								<span style="COLOR: #000000">.hashCode())<br /></span>
								<span style="COLOR: #008080">4</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />  .append(field1)<br /></span>
								<span style="COLOR: #008080">5</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /> .append(field2)<br /></span>
								<span style="COLOR: #008080">6</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /> .append(field3)<br /></span>
								<span style="COLOR: #008080">7</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /> .toHashCode();<br /></span>
								<span style="COLOR: #008080">8</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
						</span>
				</div>
		</div>
		<div>
				<br />看起来很象equals建造器。注意有两个不同的数字在构造函数中，不能是零，而且是奇数。这些数帮助避免冲突，在各个object的hashcode值间。</div>
		<div>另外，也可以使用反射机制的方法。<br /></div>
		<div>
				<br />
				<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
						<span style="COLOR: #008080">1</span>
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
						<span style="COLOR: #000000">
								<br />
						</span>
						<span style="COLOR: #008080">2</span>
						<span style="COLOR: #000000">
								<img id="Codehighlighter1_24_79_Open_Image" onclick="this.style.display='none'; Codehighlighter1_24_79_Open_Text.style.display='none'; Codehighlighter1_24_79_Closed_Image.style.display='inline'; Codehighlighter1_24_79_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
								<img id="Codehighlighter1_24_79_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_24_79_Closed_Text.style.display='none'; Codehighlighter1_24_79_Open_Image.style.display='inline'; Codehighlighter1_24_79_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000"> hashCode() </span>
						<span id="Codehighlighter1_24_79_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_24_79_Open_Text">
								<span style="COLOR: #000000">{<br /></span>
								<span style="COLOR: #008080">3</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   </span>
								<span style="COLOR: #0000ff">return</span>
								<span style="COLOR: #000000"> HashCodeBuilder.reflectionHashCode(</span>
								<span style="COLOR: #0000ff">this</span>
								<span style="COLOR: #000000">);<br /></span>
								<span style="COLOR: #008080">4</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /> }</span>
						</span>
				</div>
		</div>
<img src ="http://www.blogjava.net/site120/aggbug/97395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-02-02 00:27 <a href="http://www.blogjava.net/site120/archive/2007/02/02/97395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Ecipse生成Javadoc乱码(编码问题)终极解决方法</title><link>http://www.blogjava.net/site120/archive/2007/02/01/97358.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Thu, 01 Feb 2007 13:21:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/02/01/97358.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/97358.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/02/01/97358.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/97358.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/97358.html</trackback:ping><description><![CDATA[
		<p>
				<br />这里面有两个指定编码问题的参数<br />1)  -encoding <em>charsetName</em><br />2) -charset <em>charsetName<br /><br /></em>第一个参数表示javadoc 程序<strong>读</strong>取java源文件时候应该采用什么编码<br />第二个参数表示javadoc 程序<strong>写</strong>html文件时采用的编码形式,并会在HTML中加入如下标签</p>
		<p>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #008080">1</span>
				<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #0000ff">&lt;!</span>
				<span style="COLOR: #ff00ff">DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"</span>
				<span style="COLOR: #0000ff">&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #008080">2</span>
				<span style="COLOR: #000000">
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #008000">&lt;!--</span>
				<span style="COLOR: #008000">NewPage</span>
				<span style="COLOR: #008000">--&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #008080">3</span>
				<span style="COLOR: #000000">
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #0000ff">&lt;</span>
				<span style="COLOR: #800000">HTML</span>
				<span style="COLOR: #0000ff">&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #008080">4</span>
				<span style="COLOR: #000000">
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #0000ff">&lt;</span>
				<span style="COLOR: #800000">HEAD</span>
				<span style="COLOR: #0000ff">&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #008080">5</span>
				<span style="COLOR: #000000">
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #008000">&lt;!--</span>
				<span style="COLOR: #008000"> Generated by javadoc (build 1.5.0) on Thu Feb 01 21:10:10 CST 2007 </span>
				<span style="COLOR: #008000">--&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #008080">6</span>
				<span style="COLOR: #000000">
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #008000">&lt;!--</span>
				<span style="COLOR: #008000">-这下面的charset随编码的不同而不同,这里面为utf-8编码--</span>
				<span style="COLOR: #008000">--&gt;</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #008080">7</span>
				<span style="COLOR: #000000">
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #0000ff">&lt;</span>
				<span style="COLOR: #800000">META </span>
				<span style="COLOR: #ff0000">http-equiv</span>
				<span style="COLOR: #0000ff">="Content-Type"</span>
				<span style="COLOR: #ff0000"> content</span>
				<span style="COLOR: #0000ff">="text/html; charset=utf-8"</span>
				<span style="COLOR: #0000ff">&gt;</span>
		</div>
		<p>
				<br />
				<br />如果文件格式为UTF8格式的,可以采用如下形式进行Generate Javadoc:<font size="5"><br />javadoc  -encoding UTF-8 -charset UTF-8 &lt;other params&gt;</font></p>
<img src ="http://www.blogjava.net/site120/aggbug/97358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-02-01 21:21 <a href="http://www.blogjava.net/site120/archive/2007/02/01/97358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何明确，完整地描述一个系统 , 欢迎大家一起讨论</title><link>http://www.blogjava.net/site120/archive/2007/01/31/96822.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Tue, 30 Jan 2007 16:54:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/01/31/96822.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/96822.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/01/31/96822.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/96822.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/96822.html</trackback:ping><description><![CDATA[如题，应该从哪些角度去看待这个系统呢？<br /><br />１，从系统功能角度去看，应该有哪几大功能，或者子系统，通过功能结构图可以描述<br />２，数据流动过程来看，每一个功能，他都应该有一个流程图，数据从哪开始，流经过哪，怎么处理，最终流到哪里....等等.<br /><font color="#808080"><font color="#000000">３，ＥＲ图，就是在数据库设计中的<strong>实体Entity  关系Relative图，与ＵＭＬ有点相像</strong></font><br /></font><br />在黑盒测试时，应该了解这些，　先从功能入手，细化每一个功能，最终的每个功能都应该有相应的操作流程.　之后遍历这些流程.　这样，思路就应该比较清晰.<br /><strong><font color="#ff1493">功能是横向，流程是纵向</font></strong>.　这有点像时序图，几个功能一排，某个功能的具体操作流程，可能会与其它功能打交道.　其它功能处理完之后，又回到原功能流程中的某一步继续执行......<br /><br /><font color="#000000"><strong><u>这就是面向过程开发　－－－－－＞　ＯＰＰ</u></strong><br />这个方法，虽然可以设计并实现出一个系统，但随着系统庞大，复杂，这样处理起来将会越来越复杂.<br />OO的出现将大大降低这个复杂度，提高灵活度，安全性<br />尤其是<strong>封装 , 多态 , 通过面向接口编程，也大大降低偶合度.<br />之后利用现成的开源框架，分层处理,如:<br /><br /></strong>针对Web应用来说有:<br /><strong>Ｗeb层/View层 -----(将请求封装为对象)--&gt;  控制层 -----&gt;  权限拦截层  ----&gt; 业务层 -----&gt; 持久层 ---------(ORMapping)----&gt; 数据库<br /></strong>每层各尽其职, 不涉及跨层操作, 只认接口,下层向上层提供操作接口, <br />就像ISO/OSI七层模型一样<br /><strong>应用层 --&gt; 表示层 ---&gt; 会话层 ---&gt; 传输层 ---&gt; 网络层 ---&gt; 数据链路层 ---&gt; 物理层 , <br /></strong>底层向上层接口服务接口<br /><br />不过通过比较,发现, <strong>这个分层图对应于OPP当中的数据流程图</strong> , 也可以说定了一个标准,一个框架, 具体的业务逻辑,可以在业务层中有不同的操作<br /><br />但从中可以发现, 不论是面向对象 , 还是面向过程 , 总体的设计应该还是 <strong><font color="#ff1493">功能是横向，流程是纵向<br /></font></strong><br />起了个头,这里面所讲得都是我的理解过程,  并非一定正确, 欢迎大家一块讨论.<br /></font><img src ="http://www.blogjava.net/site120/aggbug/96822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-01-31 00:54 <a href="http://www.blogjava.net/site120/archive/2007/01/31/96822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate对视图的映射</title><link>http://www.blogjava.net/site120/archive/2007/01/30/96814.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Tue, 30 Jan 2007 15:54:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/01/30/96814.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/96814.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/01/30/96814.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/96814.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/96814.html</trackback:ping><description><![CDATA[在Hibernate当中，视图与表是公平对待的, Hibernate把视图当成是表来处理<br />但处理主键（不能重复）时，有两种方法<br />１，可以通过组合键来设置ＩＤ<br />２，可以将基本一个表的主键作为视图的ＩＤ<br /><br />目前，我只想到这两种.　如果有更好的，大家可以共享出来一起讨论<img src ="http://www.blogjava.net/site120/aggbug/96814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-01-30 23:54 <a href="http://www.blogjava.net/site120/archive/2007/01/30/96814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈对象之间的关系</title><link>http://www.blogjava.net/site120/archive/2007/01/30/96796.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Tue, 30 Jan 2007 14:02:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/01/30/96796.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/96796.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/01/30/96796.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/96796.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/96796.html</trackback:ping><description><![CDATA[
		<p>对象与对象之间的关系有以下几种关系<br /><strong><font color="#ff1493">   1)继承<br /></font></strong>         1) 一种父子关系<br />         2) 有共同特点 , 或者有普通和特殊关系<br />         3) 如: 一种进化关系, 如: 有机物 --&gt; 蛋白质 --&gt;  微生物 --&gt; 动物 --&gt; 人 <br /><br /><font color="#ff1493"><strong>   2) 依赖<br /></strong></font>         1) 就是一个<strong>对象</strong>调用被依赖对象中的某些方法而得以完成这个<strong>对象</strong>的一些职责<br />         2) 这是一种比较松散的关系 , 并且这是短期的. 我们的过程与对象往往依赖于我们的实体域对象<br />         3) 如: WebWork中的Action 依赖于 业务层中的方法 ,  业务层中的Service或者Bussiness依赖于持久层(DAO)中的方法等等 ( 如果碰到这种关系 , 通常用<strong><u>面向接口编程</u></strong>的方法来处理, 使其具有更好的扩展性, 维护性)<br /><br /><font color="#ff1493"><strong>   3) 关联<br /><br /></strong></font>         1) 指一个类指到另一个类中的属性.<br /><br />         2) 而且是长期的 <br /><br />         3) 关联关系又可以分为以下几种<br />               0) <strong>一般关联</strong>: 只要一个对象联系到另外一个对象就形成了关联关系<br /><br />               1) <strong>聚合关系</strong> , 较强于一般关联 , 有整体与局部之间的关系,并且没有了整体,局部也可单独存在,如小组与小组里面的成员,  小组不存在, 成员也可单独存在 ,  也可加入其它小组, 又如: 一个分子由多个原子按一定的结构,排列组织而成,<strong><u> 在化学变化时(针对原子的操作),按这个角度去看</u></strong> , 原子之间会脱离开,另外合成另一种物质. 其组成关系可以共享<br /><br />               2) <strong>组合关系</strong> , 也叫合成关系 , 是一种更强的整合与局部的关系 , 其关系更加紧密 ., 如: 一个分子由多个原子按一定的结构组织而成, <strong><u>在物理变化中(针对分子的操作), 按这个角度去看</u></strong> , 分子间发生变化 , 变成另一种状态, 但分子结构不变, 还是这种物质. 其组成关系多原子组成结构不可以共享.<br /><br />----------------------------------------------------------------------------------------------------------------</p>
<img src ="http://www.blogjava.net/site120/aggbug/96796.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/site120/" target="_blank">姜利阳</a> 2007-01-30 22:02 <a href="http://www.blogjava.net/site120/archive/2007/01/30/96796.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Javascript或者Java当中判断润年【最最简单的】方法</title><link>http://www.blogjava.net/site120/archive/2007/01/15/94049.html</link><dc:creator>姜利阳</dc:creator><author>姜利阳</author><pubDate>Mon, 15 Jan 2007 14:05:00 GMT</pubDate><guid>http://www.blogjava.net/site120/archive/2007/01/15/94049.html</guid><wfw:comment>http://www.blogjava.net/site120/comments/94049.html</wfw:comment><comments>http://www.blogjava.net/site120/archive/2007/01/15/94049.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/site120/comments/commentRss/94049.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/site120/services/trackbacks/94049.html</trackback:ping><description><![CDATA[Javascript测试函数isSmoothYear()<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080"> 1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">script language</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">javascript</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> isSmoothYear </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">(year)<br /></span><span style="COLOR: #008080"> 3</span><span style="COLOR: #000000"><img id="Codehighlighter1_67_121_Open_Image" onclick="this.style.display='none'; Codehighlighter1_67_121_Open_Text.style.display='none'; Codehighlighter1_67_121_Closed_Image.style.display='inline'; Codehighlighter1_67_121_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_67_121_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_67_121_Closed_Text.style.display='none'; Codehighlighter1_67_121_Open_Image.style.display='inline'; Codehighlighter1_67_121_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />    </span><span id="Codehighlighter1_67_121_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_67_121_Open_Text"><span style="COLOR: #000000">{<br /></span><span style="COLOR: #008080"> 4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Date(year , </span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"> , </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">).getDate() </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">29</span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080"> 5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 6</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    alert(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">2004年 是润年吗? \t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> isSmoothYear(</span><span style="COLOR: #000000">2004</span><span style="COLOR: #000000">));<br /></span><span style="COLOR: #008080"> 7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    alert(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">2005年 是润年吗? \t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> isSmoothYear(</span><span style="COLOR: #000000">2005</span><span style="COLOR: #000000">));<br /></span><span style="COLOR: #008080"> 8</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    alert(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">2006年 是润年吗? \t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> isSmoothYear(</span><span style="COLOR: #000000">2006</span><span style="COLOR: #000000">));<br /></span><span style="COLOR: #008080"> 9</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    alert(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">2007年 是润年吗? \t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> isSmoothYear(</span><span style="COLOR: #000000">2007</span><span style="COLOR: #000000">));<br /></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    alert(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">2008年 是润年吗? \t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> isSmoothYear(</span><span style="COLOR: #000000">2008</span><span style="COLOR: #000000">));<br /></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span></div><br />Java代码同理<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080"> 1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080"> 2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /></span><span style="COLOR: #008080"> 3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> TestDate <br /></span><span style="COLOR: #008080"> 4</span><span style="COLOR: #000000"><img id="Codehighlighter1_37_162_Open_Image" onclick="this.style.display='none'; Codehighlighter1_37_162_Open_Text.style.display='none'; Codehighlighter1_37_162_Closed_Image.style.display='inline'; Codehighlighter1_37_162_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_37_162_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_37_162_Closed_Text.style.display='none';