??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品对白刺激久久久,久久久久久久久久久久电影,久久国产主播精品http://www.aygfsteel.com/vikings/category/1406.htmlzh-cnFri, 02 Mar 2007 06:29:52 GMTFri, 02 Mar 2007 06:29:52 GMT60Tapestry 4.0 beta 新特?-7http://www.aygfsteel.com/Vikings/articles/18825.htmlVikingsVikingsTue, 08 Nov 2005 10:00:00 GMThttp://www.aygfsteel.com/Vikings/articles/18825.htmlhttp://www.aygfsteel.com/Vikings/comments/18825.htmlhttp://www.aygfsteel.com/Vikings/articles/18825.html#Feedback0http://www.aygfsteel.com/Vikings/comments/commentRss/18825.htmlhttp://www.aygfsteel.com/Vikings/services/trackbacks/18825.html Tapestry4新特??-源代码标注的异常处理 Tapestry本来提供的debug功能十分强大,4.0版本中提供了更加详细的报错机Ӟ可以昄错误的代码,q在报错的地方加亮标注,具体截图L附g(谁能告诉我怎么多余的照片删除呀)
x1pc_jqddVOWRleOL7C8xpqaKS3AGUAvBT1MIRFANda_NKbU4VLeU4oBwzLDK28sn7jVevA1K85S_hQ00Oz6G95NKXye0F245JuqXGvav5vixzNs9HU6A4cW4wlt3uPg1dt.jpg

Tapestry4新特??-Friendly URLs
Tapestry4.0以前版本中的URL一直被人所诟病Q当然现在已l有很多的解x
案,4.0版本中已l对此做了改q,
因ؓ现在的版本需要通过hivemind来配|,所以需要设|hivemind.xml中的一些属
性,具体配置如下Q?BR><?xml version="1.0"?> 
<module id="tapestry4" version="1.1.0">
 <contribution configuration-id="tapestry.url.ServiceEncoders">
  <page-service-encoder id="page" extension="html" service="page"/>
  <direct-service-encoder id="direct" stateless-extension="direct"
   stateful-extension="sdirect"/>
  <asset-encoder id="asset" path="/assets/"/>
  <extension-encoder id="extension" extension="svc" after="*"/>
 </contribution>
</module>

同时web.xml中加入映:
<servlet>
<servlet-name>tapestry4</servlet-name>
<servlet-class> org.apache.tapestry.ApplicationServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>tapestry4</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>tapestry4</servlet-name>
<url-pattern>*.direct</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>tapestry4</servlet-name>
<url-pattern>*.sdirect</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>tapestry4</servlet-name>
<url-pattern>/assets/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>tapestry4</servlet-name>
<url-pattern>*.svc</url-pattern>
</servlet-mapping>
如果希望首页的调用不是通过/app来映,可以在web.xml中更改redirectQ?BR><filter-name>redirect</filter-name>
<filter-class>org.apache.tapestry.RedirectFilter</filter-class>
<init-param>
<param-name>redirect-path</param-name>
<param-value>/Home.html</param-value>
</init-param>
</filter>
q样键入http://localhost:8080/tapestry4Q系l导航到http://localhost:
8080/tapestry4/Home.html,
d一个Page面例如Test.pageQ在Home.html中加?lt;a href="#"
jwcid="@PageLink" page="Test">test</a>Q?BR>在生成的Home.html中生成的test的链接地址为:http://localhost:
8080/tapestry4/Test.html

Tapestry4新特??-自动定位面cL?/STRONG>

关于此特性的介绍请参考:http://jakarta.apache.org/tapestry/current/UsersGuide/page-class.html 说明Q?BR>通俗点说是您可以不定义.page文g或者定义的.page文g中不指定class 属性,而让服务器自动根?html文g的\径来L对应的类文g?配置Q?BR>?application的定义文件中dQ? q样如果在文档根目录下有个Home.html文gQ你可以将Home.java攑ֈ org.edynasty.pages(实际开发中配置为您自己的包?包中Qtapestry自动Ҏ Home.hmtl构造org.edynasty.pages.Home来定位页面的cL?当然您也可以在WEB -INF目录下放一个Home.page,不需要定义class属性,tapestry自动按照上边的原 理定位?效果Q?BR>q样您可以不需要维?page中的class属性,直接Ҏ.html文g来写对应 的类文g。而且可以Ҏ业务逻辑来定义目录结构,例如?org.edynasty.pages.user定义为user相关的类Q?html也就可以攑ֈuser目录?边,目录l构如下Q?user/ListUsers.html user/EditUser.html course/ListCourses.html course/EditCourses.html Home.html


Tapestry4新特??-Application和Session范围对象的?/STRONG>
Application和Session范围对象的?BR>
关于此特性的介绍请参考:http://jakarta.apache.org/tapestry/UsersGuide/state.html
说明Q?BR>Application和Session范围的概念就不说了,T4以前的版本只可以分别指定一个对象,
以前版本的定义如?
<property name="org.apache.tapestry.visit-class" value="your.package.Visit"/>
<property name="org.apache.tapestry.global-class" value="your.package.Global"/>,
T4中可以指定Q意多的对象,而且默认的visit和global仍然可以使用?BR>
配置Q在hivemodule.xml的定义文件中dQ?BR><contribution configuration-id="tapestry.state.ApplicationObjects">
<state-object name="applicationUser" scope="application">
<create-instance class="org.edynasty.model.User"/>
</state-object>
<state-object name="sessionUser" scope="session">
<create-instance class="org.edynasty.model.User"/>
</state-object>
</contribution>
两个user分别对应Application和Session范围Q在需要用user的page中注入:
<inject property="applicationUser" type="state" object="applicationUser"/>
<inject property="sessionUser" type="state" object="sessionUser"/>Q通过
getter和setterҎ调用?BR>
效果Q怎么说呢Q可以不需要在一个visit中定义N多属性,因ؓSession的创建需要资源,
只要操作一个visit的属性,需要创建整个visitQ分别定义之后,可以在需要存取时分别创徏?/TD>


Vikings 2005-11-08 18:00 发表评论
]]>
TapeStry 4.0 beta 新特?1-3http://www.aygfsteel.com/Vikings/articles/18824.htmlVikingsVikingsTue, 08 Nov 2005 09:55:00 GMThttp://www.aygfsteel.com/Vikings/articles/18824.htmlhttp://www.aygfsteel.com/Vikings/comments/18824.htmlhttp://www.aygfsteel.com/Vikings/articles/18824.html#Feedback0http://www.aygfsteel.com/Vikings/comments/commentRss/18824.htmlhttp://www.aygfsteel.com/Vikings/services/trackbacks/18824.htmlhttp://spaces.msn.com/members/jface/PersonalSpace.aspx?_c01_blogpart=blogmgmt&_c=blogpart

Tapestry4新特?一)Qdefault binding types

一、default binding types(默认的绑定类?
    每一个组件的参数都可以定义默认的l定cdQ如果一个绑定的参数没有前缀Q将使用默认的绑定类型?BR>    下面的代码实现同L功能:

   

     加粗的部分显C前后的变化Q之所以可以这样定义,是因为Insertlg定义value参数的默认绑定类型ؓongl.
     注意Q默认的l定参数L可以被显式的l定声明覆盖掉?BR>    如果没有定义默认的绑定参敎ͼ那么在html模板中定义的默认l定参数为literalQ页面定义文仉的默认绑定参Cؓognl

修订Q?/STRONG>

从beta4版本开始,此特性已l被删除Q?

Beta4的change logQ?/P>

 Remove default-binding attribute from element(HLS)

但是“如果没有定义默认的l定参数Q那么在html模板中定义的默认l定参数为literalQ页面定义文仉的默认绑定参Cؓognl”这个效果经试依然存在?

怀念:

此段文字在beta3中存在,beta4后就删掉了!

Binding Type Defaults

Tapestry 4.0 introduces a new idea: default binding types. Each component parameter may define a default binding type (using the default-binding attribute of the element).

If a binding reference does not have a prefix, the default binding type is used.

Because of this, the following two snippets are identical:

This works because the Insert component defines the default-binding for the value parameter to be "ognl". Likewise, the source and value parameters of the Foreach component are defined to be "ognl". However, the element parameter of the Foreach component has a binding type of "literal".

This is a decision made by the component author. If a particular parameter is (nearly) always bound using a particular binding type, then a default-binding may be set. The default binding can always be overriden with an explicit binding type prefix.

What about parameters that don't define a default binding type? The answer to this question (which includes all informal parameters), is that it depends on whether the parameter is bound in an HTML template, or in a page or component specification. In an HTML template, the default binding type is "literal". In a specification, the default binding type is "ognl".



Tapestry4新特??Qlistener method
二、listener method
     如果使用qtapestry的应该知道listenerҎ?.X以前版本中的定义Q如public void formSubmit(IRequestCycle cycle)Q方法必?BR>有一个IRequestCycle参数。参数的取得方式如下QObject[] parameters = cycle.getServiceParameters();
     ?.X中参数的取得可以通过以下两种方式Q?BR>
  1. 调用IRequestCycle.getListenerParameters()Ҏ,需要传入IRequestCycle实例作ؓ参数?
  2. 按照参数的声明顺序依ơ定义ؓlistenerҎ的参数?/LI>

     W二U方法比较符合Y件的设计思维Q而且参数的类型在传入后保存,而不是想象中的统一Stringcd?BR>例如Q?BR>. . .
其中objectId为StringcdQindex为intQ声明中使用了默认的参数l定cd?
对应的方法声明如?
public void doClick(String objectId, int index)
{ . . . }
此ؓW二U方式,可见Ҏ的定义符合自然习惯,当然你也可以通过传统的方法,如下所C: public void doClick(IRequestCycle cycle)
{ Object[] parameters = cycle.getListenerParameters();
String objectId = (String)parameters[0];
int index = ((Integer)parameters[1]).intValue(); . . . } 
q种方式是ؓ了向后兼容以前的版本Q当然也适用那种参数数目不确定的情况?Tapestry默认搜烦以下的方法声明:

  • public void method(parameters)Q页面的跌{ cycle.activate()如何实现Q)
  • public void method(IRequestCycle cycle, parameters) Q們֐于用此方式Q?
  • public void method()Q无需参数传递和面跌{的情况,估计可能性不大)
  • public void method(IRequestCycle cycle)Q传l方式)
   不要试图通过参数的类型来映射listenerҎQtapestry是根据参数的数目来确定方法的?BR>
Tapestry4新特??Qglobal property source
三、Global Property Source(全局的消息属性配|?
消息属性配|听h不是很舒服,暂时q样U呼好了Q消息属性配|也是通称的国际化?BR>|,通过配置一个properties文g使不同语a的浏览者看到对应语a的版本,一?BR>的用如下,一个page面Q例如example.page,同目录下放一?BR>example.properties,?example.html中?SPAN key="key">来指定显C|
中文可以使用example_zh_CN.properties来配|。看h挺方便的Q可
tapestry4.0以前的版本的国际化不支持全局的属性配|文Ӟ必须每个面定义
自己的,无法几个面׃nQ但实际开发中Q多面׃n属性配|是很常见的Q?BR>tapestry4.0中可以通过以下方式获得全局的属性配|文Ӟ
创徏一个跟你的目全局配置文gQ如yourApp.application,此文件在4.0以前?BR>版本中是必须的,4.0中如果没有必要配|,可以不需要此文g(扯远?,yourApp
是根据你在web.xml定义的,例如

tapesty4
org.apache.tapestry.ApplicationServlet
1

那属性定义文件就应该是tapestry4.properties,q样在此文g中定义一个:test=
试Q在Home.html中?lt; span key="test">test,看到“测试”正显C?BR>


Vikings 2005-11-08 17:55 发表评论
]]>
Jive论坛与Spring框架,l典代码和架? http://www.aygfsteel.com/Vikings/articles/4815.htmlVikingsVikingsWed, 18 May 2005 15:46:00 GMThttp://www.aygfsteel.com/Vikings/articles/4815.htmlhttp://www.aygfsteel.com/Vikings/comments/4815.htmlhttp://www.aygfsteel.com/Vikings/articles/4815.html#Feedback0http://www.aygfsteel.com/Vikings/comments/commentRss/4815.htmlhttp://www.aygfsteel.com/Vikings/services/trackbacks/4815.html板桥里h http://www.jdon.com 2004/07/01

  没有一U新技术是凭空诞生的,它的萌芽或胚胎L或多或少昄于以前的技术中QJive论坛是大家潜心研I的设计型应用程序,其相兌析可见本栏的GoF设计模式专栏?/P>

  Jive和Spring同ؓ由JavaBeansl成的J2EE WebpȝQJive作ؓ早期成功设计案例Q其主要架构成ؓ大多数纯JavaBeanspȝ的流行架构,Spring也不例外?/P>

  Spring框架除了是一UWeb层应用框Ӟq提供了讉KEJB层的接口Q也有JDBC/ORM的直接操作。Spring框架主要力是用IoC模式和AOP实现了Jivepȝ的通用功能Q从而得Jiveq样的纯JavaBeans架构设计可以重用在其它系l中?/P>

  如果你感慨于Jive的设计理念,但是又苦于无法重用其设计ӞSpring框架已经帮你实现了?/P>

  同时也要注意刎ͼSpring框架cM“杂烩”,它包含了很多J2EE应用的工Pcd对EJB的调用,它的MVC与Struts JSF也是相竞争的Q以UIoc和AOP设计来说QSpring框架也是一U很重的(Heavy、Weight)框架。Spring框架是复杂的Q如果想以Spring替代EJBQ那么无疑按了葫芦QL?/P>

  Jive论坛和Spring框架联系hQ会帮助更多理解设计模式的程序员q速掌握最新的设计思潮Q而不是一U蟩跃式的强q接受。如果你对Jive有很好的研究Q将会发现Spring框架是Jive设计的更加通用的提升?/P>

  在Jive?ForumFactory是整个系l的入口和突破点QJive通过ForumFactory整个系l掌控在一个工厂模式下Q这样做的好处是Q便于控制系l的JavaBeansQ例如,客户端通过ForumFactory可创Z个Forum或访问一个ForumQ但是是否有权限讉K呢?如下图:


  
   Jive通过ForumFactory这U访问引导到相应的ProxycdQ如ForumFactoryProxycȝQ通过代理模式对这些类q行权限控制讉K。这是代理模式的一个主要用处,但是研读Jive的代理模式会发现Q要为每个类实现一个Proxyc,非常琐碎Q有没有更优雅的方式呢? 当然使用动态代理?/P>

  Spring框架基本是抽象上q设计,Spring框架Ҏ有JavaBeans的管理也是基于一个d口Bean Factory机制Q不同的是,BeanFactory可以 理所有应用的JavaBeansQ用者只要将自己的JavaBeans通过配置文g告诉BeanFactoryQ那么BeanFactory会加蝲q些JavaBeansQ例如:

  <beans>
    <bean id="exampleBean" class="eg.ExampleBean"/>
    <bean id="anotherExample" class="eg.ExampleBeanTwo"/>
  </beans>

  在Jive中,ForumFactory加蝲Jive自己的JavaBeans是通过工厂实现DbForumFactory实现的,如下代码QDbForumFactory引发了后Cpd功能实现Q这是纵向,而return new ForumFactoryProxyq个语句则类似引来一个切面,从一个横向方面实C权限讉K{功能:

private static String className = "com.jivesoftware.forum.database.DbForumFactory";

public static ForumFactory getInstance(Authorization authorization) {
     //If no valid authorization passed in, return null.
     if (authorization == null) {
       return null;
     }
     //以下使用了Singleton 单态模?
     if (factory == null) {
       synchronized(initLock) {
         if (factory == null) {
             ......

          try {
               //动态{载类
               Class c = Class.forName(className);
               factory = (ForumFactory)c.newInstance();
           }
           catch (Exception e) {
               return null;
           }
         }
       }
     }

     //Now, q回 proxy.用来限制授权对forum的访?
     return new ForumFactoryProxy(authorization, factory,                     factory.getPermissions(authorization));
   }

  既然Spring框架也是通过一个Bean Factory加蝲所有的c,那么它是如何加蝲的?通过IoC模式Q也是依赖性注模式。在我以前文章?A target=_blank>IoC模式”中Q我比较了Factory工厂模式创徏对象和Ioc模式的注对象实C间的异同QIoc相比工厂模式则更加解耦了调用者和被调用者之间关p,使用Ioc模式Q无需在调用者代码中涉及被调用者的具体实现?/P>

  Spring框架不但可以向自己容器中注射应用者自己定义的JavaBeansQ也是创徏它们Q,而且也可以向q些JavaBeans通过setҎ实现数据赋倹{?/P>

  一旦Bean Factoryq行时刻掌管q些Ȁzȝ对象QSpring通过AOP方式Q从一个横切面些JavaBeans提供了权限访问、事务锁{通用功能的实玎ͼq种实现是基于动态代理模式,而动态代理是AOP实现的一U方式?/P>

  前面提到QJive中用代理模式实现权限访问,比代理模式更加简z和抽象的是动态代理,使用动态代理将使得调用者无需指定被调用者的代理c,q是动态代理区别代理模式的本质?/P>

  动态代理这一优势Q又可以体现在另外一句话语上Q动态代理拦截了调用者对被调用者的调用Q正是这一功能W合了AOP的拦截器功能QؓAOP实现提供了可能?/P>

  Spring框架使用了动态代理实现的AOPQ正是通过动态代理机制拦截了外界对Bean Factory理下的对象的调用。如下图Q?/P>

 

  以上只是大体解构了Spring的架构,Spring框架在这个架构下Q还带了很多其它功能,如Web MVC?DAO JDBC?DAO ORM 、以及remoteQ后者类似我设计的EJBҎ调用框架?/P>

  MQSpring实是Ioc和AOP的完应用,Ioc用来装蝲JavaBeansQ创些对象;AOP用来拦截q些对象的用,q才是框架设计的必然l典方式?/P>

 

ZT:
http://www.zahui.com/html/6/40477.htm



Vikings 2005-05-18 23:46 发表评论
]]>
EJB 工作原理 (ZT) -相见恨晚http://www.aygfsteel.com/Vikings/articles/4013.htmlVikingsVikingsTue, 03 May 2005 19:04:00 GMThttp://www.aygfsteel.com/Vikings/articles/4013.htmlhttp://www.aygfsteel.com/Vikings/comments/4013.htmlhttp://www.aygfsteel.com/Vikings/articles/4013.html#Feedback0http://www.aygfsteel.com/Vikings/comments/commentRss/4013.htmlhttp://www.aygfsteel.com/Vikings/services/trackbacks/4013.html原帖: xanada ----
http://www.hibernate.org.cn/viewtopic.php?t=3832&postdays=0&postorder=asc&start=0


前两天在q个版块的精华区里翻CRobbin关于EJB的调用原理的分析Q受益非,但感觉用U文字来表达效果g不够直观Q而且对RMI的阐qC略嫌了些。这里我Ҏ自己的一点体会,在Robbin帖子的基上再来说说这个话题,供大家参考?

首先Q我惛_说说RMI的工作原理,因ؓEJB毕竟是基于RMI的嘛。废话就不多讲了QRMI的本质就是实现在不同JVM之间的调用,工作原理囑֦下:



它的实现Ҏ是在两个JVM中各开一个Stub和SkeletonQ二者通过socket通信来实现参数和q回值的传递?

有关RMI的例子代码网上可以找C,但绝大部分都是通过extend the interface java.rmi.Remote实现Q已l封装的很完善了Q不免人有N看花的感觉。下面的例子是我在《Enterprise JavaBeans》里看到的,虽然很粗p,但很直观Q利于很快了解它的工作原理?

1. 定义一个Person的接口,其中有两个business method, getAge() 和getName()

java代码: 


public interface Person {
    public int getAge() throws Throwable;
    public String getName() throws Throwable;
}



2. Person的实现PersonServerc?
java代码: 


public class PersonServer implements Person {
    int age;
    String name;

    public PersonServer(String name, int age) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}



3. 好,我们现在要在Client机器上调用getAge()和getName()q两个business methodQ那么就得编写相应的Stub(Client?和Skeleton(Server?E序。这是Stub的实玎ͼ
java代码: 


import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;

public class Person_Stub implements Person {
    Socket socket;

    public Person_Stub() throws Throwable {
        // connect to skeleton
        socket = new Socket("computer_name", 9000);
    }

    public int getAge() throws Throwable {
        // pass method name to skeleton
        ObjectOutputStream outStream =
            new ObjectOutputStream(socket.getOutputStream());
        outStream.writeObject("age");
        outStream.flush();

        ObjectInputStream inStream =
            new ObjectInputStream(socket.getInputStream());
        return inStream.readInt();
    }

    public String getName() throws Throwable {
        // pass method name to skeleton
        ObjectOutputStream outStream =
            new ObjectOutputStream(socket.getOutputStream());
        outStream.writeObject("name");
        outStream.flush();

        ObjectInputStream inStream =
            new ObjectInputStream(socket.getInputStream());
        return (String)inStream.readObject();
    }
}



注意QPerson_Stub和PersonServer一P都implements Person。它们都实现了getAge()和getName()两个business methodQ不同的是PersonServer是真的实玎ͼPerson_Stub是徏立socketq接Qƈ向Skeleton发请求,然后通过Skeleton调用PersonServer的方法,最后接收返回的l果?

4. Skeleton实现
java代码: 


import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.ServerSocket;

public class Person_Skeleton extends Thread {
    PersonServer myServer;

    public Person_Skeleton(PersonServer server) {
        // get reference of object server
        this.myServer = server;
    }

    public void run() {
        try {
            // new socket at port 9000
            ServerSocket serverSocket = new ServerSocket(9000);
            // accept stub's request
            Socket socket = serverSocket.accept();

            while (socket != null) {
                // get stub's request
                ObjectInputStream inStream =
                    new ObjectInputStream(socket.getInputStream());
                String method = (String)inStream.readObject();

                // check method name
                if (method.equals("age")) {
                    // execute object server's business method
                    int age = myServer.getAge();
                    ObjectOutputStream outStream =
                        new ObjectOutputStream(socket.getOutputStream());

                    // return result to stub
                    outStream.writeInt(age);
                    outStream.flush();
                }

                if(method.equals("name")) {
                    // execute object server's business method
                    String name = myServer.getName();
                    ObjectOutputStream outStream =
                        new ObjectOutputStream(socket.getOutputStream());

                    // return result to stub
                    outStream.writeObject(name);
                    outStream.flush();
                }
            }
        } catch(Throwable t) {
            t.printStackTrace();
            System.exit(0);
        }
    }

    public static void main(String args []) {
        // new object server
        PersonServer person = new PersonServer("Richard", 34);

        Person_Skeleton skel = new Person_Skeleton(person);
        skel.start();
    }
}



Skeletonc?extends from ThreadQ它镉K在后台运行,随时接收client发过来的request。ƈҎ发送过来的key去调用相应的business method?

5. 最后一个,Client的实?
java代码: 


public class PersonClient {
    public static void main(String [] args) {
        try {
            Person person = new Person_Stub();
            int age = person.getAge();
            String name = person.getName();
            System.out.println(name + " is " + age + " years old");
        } catch(Throwable t) {
            t.printStackTrace();
        }
    }
}



Client的本质是Q它要知道Person接口的定义,q实例一个Person_StubQ通过Stub来调用business methodQ至于Stub怎么dServer沟通,Client׃用管了?

注意它的写法Q?
Person person = new Person_Stub();
而不?
Person_Stub person = new Person_Stub();

Z么?因ؓ要面向接口编E嘛Q呵c?

感谢您有耐心看到q里Q关于RMIQ我惌的就q么多了。但是好象还没写到EJBQ本人就累了个半死,了Q我q是先去睡觉Q明天再往下箋吧。。?BR>
本h没有用过WeblogicQ这里就l合WebSphere来讲讲各个类的调用关pd?

假定我们要创Z个读取User信息的SessionBeanQ需要我们写的有3个文Ӟ
1. UserServiceHome.java
Home接口

2. UserService.java
Remote接口

3. UserServiceBean.java
Bean实现

WSAD最l会生成10个class。其?个是什么呢Q我们一个一个数q来Q?

4. _UserServiceHome_Stub.java
q个当然是Home接口在Client?动态加?的StubcMQ它implements UserServiceHome?

5. _EJSRemoteStatelessUserServiceHome_a940aa04_Tie.java
Home接口在Server端的Skeletonc,"a940aa04"应该是随机生成的Q所有其他的相关class名里都会有这个标志串QTie是Corba对Skeleton的叫法?

6. EJSRemoteStatelessUserServiceHome_a940aa04.java
Home接口在Server端的实现Q当Ӟ它也implements UserServiceHome?

7. EJSStatelessUserServiceHomeBean_a940aa04.java
?6调用Qcreate _UserService_Stub?Z?6不能直接create _UserService_Stub呢?后面再讲?

8. _UserService_Stub.java
Remote接口在Client?动态加?的StubcR它implements UserService?

9. _EJSRemoteStatelessUserService_a940aa04_Tie.java
Remote接口在Server端的SkeletoncR?

10. EJSRemoteStatelessUserService_a940aa04.java
Remote接口在Server端的实现Q当Ӟ它也implements UserService。ƈ且,它负责调用UserServiceBean——也是我们所写的Bean实现cZ—里面的business method?

那么Q各个类之间的调用关pd底是怎么L呢?单的_是两次RMI循环?BR>
先来看看Client端的E序是怎么写的Q?

java代码: 


try {
    InitialContext ctx = new InitialContext();

    //W一?/SPAN>
    UserServiceHome home =
        (UserServiceHome) PortableRemoteObject.narrow(
            ctx.lookup(JNDIString),
            UserServiceHome.class);

    //home: _UserServiceHome_Stub
    System.out.println(home.toString());

    //W二?/SPAN>
    UserService object = home.create();

    //ojbect: _UserService_Stub
    System.out.println(object.toString());

    //W三?/SPAN>
    int userId = 1;
    UserInfo ui = object.getUserInfo(userId);
}



在第一步之后,我们得到了一个UserServiceHome(interface)定义的对象homeQ那么,home到底是哪个class的instance呢?用debug看一下,知道了home原来是_UserServiceHome_Stub的实例?

从第二步开始,是我们的关注所在,虽然只有单的一行代码,
UserService object = home.create();
但是他背后的pȝ是怎么q做的呢Q我们进入代码来看吧Q?

1. 调用home.create()
java代码: 


UserServiceHome home;
UserService obj = home.create();



2. 实际是调用_UserServiceHome_Stub.create()Q在q个Ҏ里面QStub向Skeleton发送了一个create的字Ԍ
java代码: 


org.omg.CORBA.portable.OutputStream out = _request("create", true);
in = (org.omg.CORBA_2_3.portable.InputStream)_invoke(out);



3. Server端的Skeleton接收Stub发来的requestQƈ调用相应的方法:
java代码: 


_EJSRemoteStatelessUserServiceHome_a940aa04_Tie._invoke() {
    ......
    switch (method.length()) {
        case 6:
            if (method.equals("create")) {
                return create(in, reply);
            }
        ......
    }
}



java代码: 


_EJSRemoteStatelessUserServiceHome_a940aa04_Tie.create() {
    EJSRemoteStatelessUserServiceHome_a940aa04 target = null;
    result = target.create();
    org.omg.CORBA.portable.OutputStream out = reply.createReply();
    Util.writeRemoteObject(out,result);
    return out;
}



4. Skeleton调用的是UserServiceHome的Server端实现类的createҎ
java代码: 


EJSRemoteStatelessUserServiceHome_a940aa04.create() {
    UserService _EJS_result;
    _EJS_result = EJSStatelessUserServiceHomeBean_a940aa04.create();
}



5. #4又调用EJSStatelessUserServiceHomeBean_a940aa04.create()
java代码: 


    UserService result = super.createWrapper(new BeanId(this, null));



xQ我们终于结束了W一个RMI循环Qƈ得到了Remote接口UserService的Stubc_UserService_StubQ就?5里面的result?

q里有一个问题,Z?4不直接create _UserService_StubQ而又转了一?5的手呢?因ؓ#4 extends from EJSWrapperQ它没有能力create StubQ因此必d助#5Qwhich extends from EJSHomeQ这h可以生成一个Stub。如果不是ؓ了生成这个StubQ应该可以不?5q一步?BR>
OK, now we got the object which is instanceOf _UserService_Stub, and implements UserService

现在我们的Client端走到第三步了:
UserInfo ui = object.getUserInfo(userId);

l箋看代码,开始第二个RMI循环Q?

1. 调用object.getUserInfo()
java代码: 


UserService object;
object.getUserInfo(userId);



2. 实际是调用_UserService_Stub.getUserInfo(int arg0)Q在q个Ҏ里面QStub向Skeleton发送了一个getUserInfo的字串和arg0q个参数Q?

java代码: 


org.omg.CORBA.portable.OutputStream out = _request("getUserInfo", true);
out.write_long(arg0);
in = (org.omg.CORBA_2_3.portable.InputStream)_invoke(out);



3. Server端的Skeleton接收Stub发来的requestQƈ调用相应的方法:
java代码: 


_EJSRemoteStatelessUserService_a940aa04_Tie._invoke() {
    switch (method.charAt(5))
    {
        case 83:
            if (method.equals("getUserInfo")) {
                return getUserInfo(in, reply);
            }
        ......
    }
}

_EJSRemoteStatelessUserService_a940aa04_Tie.getUserInfo() {
    EJSRemoteStatelessUserService_a940aa04 target = null;
    int arg0 = in.read_long();
    UserDTO result = target.getUserInfo(arg0);
    org.omg.CORBA_2_3.portable.OutputStream out = reply.createReply();
    out.write_value(result,UserDTO.class);
    return out;
}



4. Skeleton调用的是UserService的Server端实现类的getUserInfoҎ
java代码: 


EJSRemoteStatelessUserService_a940aa04.getUserInfo() {
    UserServiceBean _EJS_beanRef = container.preInvoke(this, 0, _EJS_s);
    _EJS_result = _EJS_beanRef.getUserInfo(id);
}



最后的最后,#4l于调用了我们写的UserServiceBean里的getUserInfoҎQ这才是我们真正惌d的事情?

xQ第二个RMI循环也终于结束了?BR>
回顾一下上面的分析Q可以很清晰的看CơRMI循环的过E,下图(见链?描述了整个流E:

http://www.pbase.com/image/27229257 
http://mk23.image.pbase.com/u42/nobo123/upload/27229257.ejb2.jpg

黄色?Q?Q?0是程序员要写的,其余是系l生成的?

#1是Home interface, #2?4都implements 了它?
#6是Remote interface, #7?9都implements 了它?
#10是Bean实现?

写到q里Q基本要说的p完了。这实在是一篏Mh的工作,希望您能E饭。欢q补充,Ƣ迎摘错。谢谢,呵呵?BR>

单讲Q就是ؓ了适应分布式开发的需要?

首先Q回到我最后给出的程图?

Client端最原始的冲动,肯定是能直接调用#10.UserServiceBeanq了。那么第一个问题来了,
Client和Server不在一个JVM?/SPAN>?

q好办,我们不是有RMI吗,好,q个问题p么解决了Q?
1. UserServiceBeanInterface.getUserInfo()
2. UserServiceBeanStub
3. UserServiceBeanSkeleton
4. UserServiceBean

用着用着Q第二个问题来了Q?
UserServiceBean只有人用Q没人管理,transaction logic, security logic, bean instance pooling logicq些不得不考虑的问题Q出水面了?

OKQ我们想到用一个delegateQEJBObjectQ来q行所有这些logic的管理。client和EJBObject打交道,EJBObject调用UserServiceBean?

注意Q这个EJBObject也是一个InterfaceQ?6.UserServiceq个interface正是从它extends而来。ƈ且EJBObject所理的这些logicQ正是AppServer的一部分?

现在的流E变ZQ?
EJBObject
1. UserService.getUserInfo()
2. UserServiceStub
3. UserServiceSkeleton
4. UserServiceImp
5. UserServiceBean

q已l和整幅N?6, #7, #8, #9, #10一一对应了?

现在能满x们的需求了吗?不,W三个问题又来了Q?
既然是分布式开发,那么我当然没理由只用一个Specified ServerQ我可能需要用到好几个不同的ServerQ而且EJBObject也需要管理呀

OKQؓ了适应你的需要,我们q得加再一个HomeObjectQ首先它来决定用哪个Server(当然Q是׃用JNDI String讑֮?Q其ơ,它来理EJBObject?

注意Q这个EJBHome也是一个InterfaceQ?1.UserServiceHomeq个interface正是从它extends而来。ƈ且EJBHome理EJBObject的logicQ也是AppServer的一部分?

现在的调用次序是
1. EJBHome.create()
2. EJBHomeStub
3. EJBHomeSkeleton
4. EJBHomeImp(EJSWrapper)
5. EJSHome

得到EJBObject

6. UserService.getUserInfo()
7. UserServiceStub
8. UserServiceSkeleton
9. UserServiceImp
10. UserServiceBean

现在已经完全和流E图的调用顺序一致了?

lg所qͼEJB的调用确实很ȝQ但是搞的这么麻烦,实是有搞的ȝ的道理,实在是不得不Z?

哎哟Q好累啊。希望我把这个问题说清楚了,您也没给我绕qL。谢谢?/SPAN>


Vikings 2005-05-04 03:04 发表评论
]]>
վ֩ģ壺 ʡ| | | | ¡| ̨| ̨| | | ˳| ɽ| | | | ɽ| Դ| | ¦| ٰ| ƽ| ҳ| | | | | ̨ǰ| | ֹ| | | | | | | | | | | | | |