• SSH深度历险(三) EJB Session Bean有状态和无状态的差别与联系


           刚開始对两种sessionbean存在误解。觉得有状态是实例一直存在,保存每次调用后的状态,并对下一次调用起作用。而觉得无状态是每次调用实例化一次,不保留用户信息。细致分析并用实践检验后,会发现,事实恰好相反:有状态和无状态会话bean的本质差别是它们的生命期。

         

           首先解释一个以下要用到的概念--用户:sessionbean 的用户实际上就是直接调用ejb的类的实例,甚至是这个实例的某个方法。同一个类的不同实例对于session bean来说是不同的用户。


    实例解析


    有状态的StatefulEjb接口


    <span style="font-size:18px;"><span style="font-size:18px;">package com.bjsxt.ejb;
    
    public interface StatefulEjb {
    	public void compute(int i);
    	public int getResult();
    
    }
    </span></span>


    StatefulEjb的实现


    <span style="font-size:18px;"><span style="font-size:18px;">package com.bjsxt.ejb;
    
    import javax.ejb.Remote;
    import javax.ejb.Stateful;
    @Stateful
    @Remote
    	
    public class StatefulEjbBean implements StatefulEjb {
    
    	private int state;
    	public void compute(int i) {
    		state = state +1;
    
    	}
    
    	
    	public int getResult() {
    		
    		return state;
    	}
    
    }
    </span></span>

    无状态接口StatelessEjb


    <span style="font-size:18px;"><span style="font-size:18px;">package com.bjsxt.ejb;
    
    public interface StatelessEjb {
    	public void compute(int i);
    	public int getResult();
    
    }
    </span></span>


    无状态接口StatelessEjb实现


    <span style="font-size:18px;"><span style="font-size:18px;">package com.bjsxt.ejb;
    
    import javax.ejb.Remote;
    import javax.ejb.Stateless;
    
    @Stateless
    @Remote
    public class StatelessEjbBean implements StatelessEjb {
    
    	private int state;
    	public void compute(int i) {
    		state = state +1;
    
    	}
    
    	
    	public int getResult() {
    		
    		return state;
    	}
    
    }
    </span></span>


    client配置jndi


    <span style="font-size:18px;"><span style="font-size:18px;">java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
    java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
    java.naming.provider.url=localhost</span></span>


    有状态的client编写

    <span style="font-size:18px;"><span style="font-size:18px;">package com.bjsxt.ejb;
    
    import javax.naming.InitialContext;
    
    public class StatefulEjbClient {
    	public static void main(String[] args) throws Exception{
    		InitialContext context = new InitialContext();
    		//第一次回話
    		StatefulEjb ejb1 =(StatefulEjb)context.lookup("StatefulEjbBean/remote");
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    	//第二次会话
    		
    		StatefulEjb ejb2 = (StatefulEjb)context.lookup("StatefulEjbBean/remote");
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    	}
    
    }
    </span></span>


    结果:



    无状态client编写
    <span style="font-size:18px;"><span style="font-size:18px;">package com.bjsxt.ejb;
    
    import javax.naming.InitialContext;
    
    public class StatelessEjbClient {
    	public static void main(String[] args) throws Exception{
    		InitialContext context = new InitialContext();
    		//第一次回話
    		StatelessEjb ejb1 =(StatelessEjb)context.lookup("StatelessEjbBean/remote");
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		System.out.print(ejb1.getResult());
    		ejb1.compute(1);
    		
    	//第二次会话
    		
    		StatelessEjb ejb2 = (StatelessEjb)context.lookup("StatelessEjbBean/remote");
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		ejb2.compute(1);
    		System.out.print(ejb2.getResult());
    		
    		System.out.println("ejb1 == ejb2 ?:"+(ejb1 == ejb2));
    		
    	}
    
    }
    </span></span>

    结果




           有状态会话bean:每一个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”。一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每一个用户最初都会得到一个初始的bean。
           无状态会话bean :bean一旦实例化就被加进会话池中。各个用户都能够共用。

    即使用户已经消亡,bean的生命期也不一定结束,它可能依旧存在于会话池中,供其它用户调用。因为没有特定的用户。那么也就不能保持某一用户的状态。所以叫无状态bean。但无状态会话bean并不是没有状态。假设它有自己的属性(变量),那么这些变量就会受到全部调用它的用户的影响。这是在实际应用中必须注意的。



         

       差别的根本原因


         

          对于有状态会话Bean来说,仅仅要有client发送对有状态会话Bean的訪问。server都会创建一个会话Bean实例与该client相应,这样这个实例与这个client就是一一相应的。

    假设client在Bean实例中保存了信息,之后还能够使用。

           对于无状态会话Bean来说,server端会维持一个实例池,创建好若干个实例对象供client调用。当从client发送创建会话Bean的请求时,并不一定会真的创建 EJB,多数情况下是从实例池中得到一个实例。用完之后又一次放回实例池。

    假设下次再訪问,再从实例池中取出一个实例使用,并不一定是上次的实例。即使两次訪问使用的是同一个实例。在两次訪问之间也有可能有其它的client訪问了该实例。所以,并不能保证在多次訪问之间的信息会被保存。所以,无状态会话Bean 不会专门保存client的信息。




       各自的优缺点

           

            由于有状态会话Bean须要保存特定client的信息,一个client相应一个实例,既是在当时client有连接没有訪问的情况下,也要为这个client保留这个实例。这样随着client数量的添加,server端须要创建的实例的数量也在添加,添加到一定程度对server的性能就会有一定的影响。为了不正确server的性能产生影响,通常server会进行一些优化。

    当client的数量超过某个值之后。就不创建新的实例。

    尽管不创建新的实例。还是须要对用户响应。这时候就採用共享实例的方式。会查看哪个实例尽管处于连接状态,可是没有訪问。然后把这个实例的状态保存起来,使用这个实例为新的请求服务。对于原来的client来说,称为挂起。

    假设原来的client又发送请求了,会又一次查找一个空暇的实例而且把已经保存好的状态恢复回来,这个过程称为激活。所以在有状态会话Bean的訪问过程。常常会发生查找实例,激活挂起等操作,所以效率比較低。

           而发送对无状态会话Bean的请求的时候,能够随便取一个空暇的实例为client服务,所以效率比較高。


           有状态会话Bean的优点是,能够保存client的状态,所以client在兴许訪问的时候就能够少传递一些參数。而无状态会话Bean须要传递方法运行过程中须要的全部參数。


       怎样选择
           依据上面分析的有状态会话Bean和无状态会话Bean的优缺点。假设要频繁的訪问。而且多次訪问之间会共享一些信息,这时候应该使用有状态会话Bean。对于不常常使用的功能,能够使用无状态会话Bean。无状态会话Bean的使用要比有状态会话Bean的使用多。

     

           项目中没有使用到有状态的会话bean。对于使用的同样数据。也是通过传递參数实现,并不是设置到bean中的属性值中。

    对于无状态的会话bean。假设有属性,则可能影响到全部调用的用户,由于他是共享的。


       总结


             通过实例自己实践之后的清晰了非常多,多动手多动手,TO Do TO DO 。

  • 相关阅读:
    Ubuntu无法初始化软件包信息
    数组名做函数的参数
    Printf函数中%p代表什么数据类型
    assert()函数用法总结
    C语言printf 格式 zz
    零值指针指向何处? zz~
    命名空间“System.Net”中不存在类型或命名空间名称“Sockets”。是否缺少程序集引用?
    AD20配置为中文显示
    sharepoint:实现搜索功能
    sharepoint:爬网完成后上传新文档搜索不到(设定爬网Schedule)
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5062997.html
Copyright © 2020-2023  润新知