验证有状态session bean和无状态session bean的区别

    技术2022-05-11  73

            stateful session bean和stateless session bean 的根本区别在于它们的生命周期不同,即有状态session bean会一直和固定的客户端保持会话, 即使被钝化;而无状态session bean则完全可以随时(当容器认为客户端结束了会话的时候)删除bean而不需要保持状态。为了验证容器处理两种bean的不同,下面写了一个简单的测试程序来测试。

            测试工具及平台: Eclipse JAVA IDE, Sun Application Server 8.

    一、首先编写好session bean:

    1) 定义远程接口

    package  mybeans; import  java.rmi.RemoteException; import  javax.ejb.EJBObject; public   interface  Count  extends  EJBObject  {    public int doCount() throws RemoteException;}

    2) 编写远程主接口

    package  mybeans; import  java.rmi.RemoteException; import  javax.ejb.CreateException; import  javax.ejb.EJBHome; public   interface  CountHome  extends  EJBHome  {    public Count create() throws RemoteException,CreateException;    public Count create(int i) throws RemoteException,CreateException;}

    3) 编写session bean

     

    package  mybeans; import  java.rmi.RemoteException; import  javax.ejb.CreateException; import  javax.ejb.EJBException; import  javax.ejb.SessionBean; import  javax.ejb.SessionContext; public   class  CountBean  implements  SessionBean  {    public int n=0;    public SessionContext ctxt;    public int doCount()    {        n++;        return n;    }    public void ejbCreate() throws RemoteException,CreateException    {            }    public void ejbCreate(int i) throws RemoteException,CreateException    {        n=i;    }    public void ejbActivate() throws EJBException, RemoteException {                System.out.println("Bean"+n/10+" Acivated.");    }    public void ejbPassivate() throws EJBException, RemoteException {        System.out.println("Bean"+n/10+" Passvated");    }    public void ejbRemove() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    public void setSessionContext(SessionContext ctxt) throws EJBException,            RemoteException {        // TODO Auto-generated method stub        this.ctxt=ctxt;    }}

    以上便是运行在容器里的EJB程序。

    二、部署这个bean

    说明:为了测试有状态与无状态会话bean的不同,我们需要分别部署这两个bean。

    启动了Sun Application Server 后需要分别进行部署,这里不说明具体过程。两个bean的部署描述文件为:

    1) ejb-jar.xml:

    <? xml version="1.0" encoding="UTF-8" ?> < ejb-jar  xmlns ="http://java.sun.com/xml/ns/j2ee"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  version ="2.1"  xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" > < display-name > CountJar </ display-name > < enterprise-beans > < session > < display-name > CountBean2 </ display-name > < ejb-name > CountBean2 </ ejb-name > < home > mybeans.CountHome </ home > < remote > mybeans.Count </ remote > < ejb-class > mybeans.CountBean </ ejb-class > < session-type > Stateless </ session-type > < transaction-type > Bean </ transaction-type > < security-identity > < use-caller-identity /> </ security-identity > </ session > < session > < display-name > CountBean </ display-name > < ejb-name > CountBean </ ejb-name > < home > mybeans.CountHome </ home > < remote > mybeans.Count </ remote > < ejb-class > mybeans.CountBean </ ejb-class > < session-type > Stateful </ session-type > < transaction-type > Bean </ transaction-type > < security-identity > < use-caller-identity /> </ security-identity > </ session > </ enterprise-beans > </ ejb-jar >

    2) sun-ejb-jar.xml:

    <? xml version="1.0" encoding="UTF-8" ?> <! DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 EJB 2.1//EN" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_2_1-1.dtd" > < sun-ejb-jar > < enterprise-beans > < unique-id > 0 </ unique-id > < ejb > < ejb-name > CountBean </ ejb-name > <jndi-name>CountBean</jndi-name> < pass-by-reference > false </ pass-by-reference > < is-read-only-bean > false </ is-read-only-bean > < refresh-period-in-seconds > -1 </ refresh-period-in-seconds > < cmt-timeout-in-seconds > 0 </ cmt-timeout-in-seconds > < gen-classes /> </ ejb > < ejb > < ejb-name > CountBean2 </ ejb-name > <jndi-name>CountBean2</jndi-name> < pass-by-reference > false </ pass-by-reference > < is-read-only-bean > false </ is-read-only-bean > < refresh-period-in-seconds > -1 </ refresh-period-in-seconds > < cmt-timeout-in-seconds > 0 </ cmt-timeout-in-seconds > < gen-classes /> </ ejb > </ enterprise-beans > </ sun-ejb-jar >

    注意黑体的部分

    三、编写测试程序

            测试程序主要思路是利用多线程技术启动3个测试bean,分别进行计数运算,通过观测结果可以得出本文的结论。

       

    package  client; import  mybeans. * ; import  javax.naming.InitialContext; import  javax.rmi.PortableRemoteObject; public   class  TestCountClient  {    public static void main(String args[])    throws Exception    {        InitialContext ctxt=new InitialContext();        CountHome countHome=null;        countHome=(CountHome)PortableRemoteObject.narrow(ctxt.lookup("CountBean"), CountHome.class); //测试有状态会话bean        //countHome=(CountHome)PortableRemoteObject.narrow(ctxt.lookup("CountBean2"), CountHome.class); 测试无状态会话bean        Count count=countHome.create(1);        Count count2=countHome.create(2);        Count count3=countHome.create(3);                BeanThread t1=new BeanThread(1,count);        BeanThread t2=new BeanThread(2,count2);        BeanThread t3=new BeanThread(3,count3);        t1.start();        t2.start();        t3.start();            }} class  BeanThread  extends  Thread {    public int n=0;    public Count count=null;    public BeanThread(int i, Count c)    {        n=i;        count=c;    }    public void run()         {        try{            for (int i=0;i<10;i++)            {                System.out.println("The current count"+n+" is: "+count.doCount());                Thread.sleep(10);            }                    }        catch (Exception e)        {                    }        super.run();    }    public synchronized void start() {        // TODO Auto-generated method stub        super.start();    }}

    注意上面的程序,测试两种会话bean需要独立进行。即先注释化掉一种情况然后才能测试另一种。

    四、测试结果

          1)  测试有状态会话bean时得出的结果如(由于多线程特点,当然结果可能与下面不完全一致):

    The current count1 is: 2The current count2 is: 3The current count3 is: 4The current count1 is: 3The current count3 is: 5The current count2 is: 4The current count1 is: 4The current count2 is: 5The current count1 is: 5The current count3 is: 6The current count1 is: 6The current count3 is: 7The current count2 is: 6The current count1 is: 7The current count3 is: 8The current count1 is: 8The current count2 is: 7The current count1 is: 9The current count3 is: 9The current count2 is: 8The current count3 is: 10The current count1 is: 10The current count3 is: 11The current count2 is: 9The current count1 is: 11The current count3 is: 12The current count2 is: 10The current count3 is: 13The current count2 is: 11The current count2 is: 12

    可以看到:上面的结果显示每个bean尽管执行交替进行,但是它们的状态还是保持的,即上次若是2,下次就是3。

            2)  测试无状态会话bean时结果如下(当然也由于多线程的特点,结果很可能和下面不一致):

    The current count3 is:  1 The current count1 is:  2 The current count2 is:  3 The current count2 is:  4 The current count3 is:  5 The current count1 is:  1 The current count2 is:  2 The current count1 is:  4 The current count3 is:  3 The current count1 is:  5 The current count2 is:  6 The current count3 is:  7 The current count1 is:  8 The current count2 is:  9 The current count2 is:  10 The current count3 is:  11 The current count1 is:  12 The current count2 is:  14 The current count1 is:  13 The current count3 is:  15 The current count2 is:  16 The current count3 is:  17 The current count1 is:  18 The current count2 is:  19 The current count1 is:  20 The current count3 is:  21 The current count2 is:  22 The current count3 is:  23 The current count1 is:  24 The current count3 is:  25

            测试结果表明:无状态会话bean确实是无法保持会话状态的。但结果同时还显示了另外一个有趣的现象,即数字很大部分是累加的,这跟容器调度bean的算法是有关的。


    最新回复(0)