刚开始对两种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>

客户端配置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>

有状态的客户端编写

<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>

结果:

无状态客户端编写

<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来说,只要有客户端发送对有状态会话Bean的访问,服务器都会创建一个会话Bean实例与该客户端对应,这样这个实例与这个客户端就是一一对应的。如果客户端在Bean实例中保存了信息,之后还可以使用。

对于无状态会话Bean来说,服务器端会维持一个实例池,创建好若干个实例对象供客户端调用。当从客户端发送创建会话Bean的请求时,并不一定会真的创建 EJB,多数情况下是从实例池中得到一个实例,用完之后重新放回实例池。如果下次再访问,再从实例池中取出一个实例使用,并不一定是上次的实例。即使两次访问使用的是同一个实例,在两次访问之间也有可能有其他的客户端访问了该实例。所以,并不能保证在多次访问之间的信息会被保存。所以,无状态会话Bean 不会专门保存客户端的信息。





   各自的优缺点

因为有状态会话Bean需要保存特定客户端的信息,一个客户端对应一个实例,既是在当时客户端有连接没有访问的情况下,也要为这个客户端保留这个实例。这样随着客户端数量的增加,服务器端需要创建的实例的数量也在增加,增加到一定程度对服务器的性能就会有一定的影响。为了不对服务器的性能产生影响,通常服务器会进行一些优化。当客户端的数量超过某个值之后,就不创建新的实例。虽然不创建新的实例,还是需要对用户响应,这时候就采用共享实例的方式。会查看哪个实例虽然处于连接状态,但是没有访问,然后把这个实例的状态保存起来,使用这个实例为新的请求服务,对于原来的客户端来说,称为挂起。如果原来的客户端又发送请求了,会重新查找一个空闲的实例并且把已经保存好的状态恢复回来,这个过程称为激活。所以在有状态会话Bean的访问过程,经常会发生查找实例,激活挂起等操作,所以效率比较低。

而发送对无状态会话Bean的请求的时候,可以随便取一个空闲的实例为客户端服务,所以效率比较高。

       有状态会话Bean的好处是,可以保存客户端的状态,所以客户端在后续访问的时候就可以少传递一些参数。而无状态会话Bean需要传递方法执行过程中需要的所有参数。





   如何选择

       根据上面分析的有状态会话Bean和无状态会话Bean的优缺点。如果要频繁的访问,并且多次访问之间会共享一些信息,这时候应该使用有状态会话Bean。对于不经常使用的功能,可以使用无状态会话Bean。无状态会话Bean的使用要比有状态会话Bean的使用多。

项目中没有使用到有状态的会话bean,对于使用的相同数据,也是通过传递参数实现,并非设置到bean中的属性值中。对于无状态的会话bean,如果有属性,则可能影响到所有调用的用户,因为他是共享的。

   总结

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

SSH深度历险(三) EJB Session Bean有状态和无状态的区别与联系的更多相关文章

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

    刚開始对两种sessionbean存在误解.觉得有状态是实例一直存在,保存每次调用后的状态,并对下一次调用起作用.而觉得无状态是每次调用实例化一次,不保留用户信息.细致分析并用实践检验后,会发现,事实 ...

  2. SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对比注解方式的优缺点)

    接上一篇 SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP 本文采用强制的CGLB代理方式 Security ...

  3. SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP

    AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...

  4. JavaEE(8) - 本地和远程调用的有状态以及无状态Session EJB

    1. 使用NetBeans开发Session Bean #1. 创建项目:File-->New Project-->Java EE-->EJB Module #2. 在项目中创建Se ...

  5. 有状态与无状态 cookie session

    服务器所维护的与客户交互活动的信息称为状态信息.不保存任何状态信息的服务器称为无状态服务器(stateless server),反之则称为有状态服务器(stateful server). 面向连接对应 ...

  6. SSH深度历险(八) 剖析SSH核心原理+Spring依赖注入的三种方式

           在java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依 ...

  7. SSH深度历险(二) Jboss+EJB的第一个实例

    学习感悟:每次学习新的知识,都会通过第一个小的实例入手,获得成就感,经典的Hello Workd实例奠定了我们成功的大门哈,这些经典的实例虽小但是五脏俱全呢,很好的理解了,Ejb的核心. 今天主要以这 ...

  8. SSH深度历险(六) 深入浅出----- Spring事务配置的五种方式

    这对时间在学习SSH中Spring架构,Spring的事务配置做了详细总结,在此之间对Spring的事务配置只是停留在听说的阶段,总结一下,整体把控,通过这次的学习发觉Spring的事务配置只要把思路 ...

  9. SSH深度历险(九) Struts2+DWZ+Uploadify实现多文件(文件和图片等等)上传

    在gxpt_uas系统中,要实现文件(文件和图片等等,可以灵活配置)的批量上传至mongodb,在学习这个过程中,学习了mongodb,并实现了批量上传的功能,实现思路:在DWZ的基础上参考官方的实例 ...

随机推荐

  1. bzoj 4025: 二分图

    Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. 解题报告: ...

  2. SpringBoot学习之SpringBoot执行器

    在以往的分布式开发当中,各个服务节点的监控必不可少.监控包含有很多方面,比如说:内存占用情况,节点是否健康等.在spring-boot会给我们提供相关资源监控叫做spring-boot-actuato ...

  3. python 类的特殊成员方法

    __doc__ # 输出类的描述信息 __module__ # 表示当前操作的对象在那个模块 __class__ # 表示当前操作的对象的类是什么 __init__ # 构造方法,通过类创建对象是,自 ...

  4. Python中内置函数的介绍

    内置函数的功能介绍 常用内置函数如下: 1.abs() 绝对值 格式:abs(x) 例如:print(abs(-18)) >>> 18 返回值:number #该函数主要用于数值类的 ...

  5. windows server 2008 R2 禁用ipv6和隧道适配器

    在windows server 2008 R2操作系统下部署weblogic web application,部署完成后进行测试,发现测试页的地址使用的是隧道适配器的地址,而不是静态的ip地址,而且所 ...

  6. android 欢迎界面的制作

    再打开手机app的时候,最先映入我们眼帘的是一个覆盖手机全屏的欢迎界面,在这个界面显示出来的时候整个手机屏幕只会显示这一个界面,上面的标题栏,以及手机最顶端的状态栏都会消失,只有欢迎页面结束跳转到其他 ...

  7. Memcached在Linux环境下的使用详解

    一.引言             写有关NoSQL数据库有关的文章已经有一段时间了,可以高兴的说,Redis暂时就算写完了,从安装到数据类型,在到集群,几乎都写到了.如果以后有了心得,再补充吧.然后就 ...

  8. spring web项目下,判断项目是否启动完成

    本文同时发布于见鬼网:https://faceghost.com/article/483341 概述:spring 加载完成后,我们有时候会做一些初始化工作,如加载一些缓存,DB,等,这里采用实现Se ...

  9. Android开发技巧——BaseAdapter的另一种优雅封装

    RecyclerView虽然因其灵活性.高效性等特点而备受好评,但也不是一定得用它把ListView给替代掉.在某些场景中,ListView还是相对更适合的.比如数据量不大,不频繁更新,并且需要简单地 ...

  10. Android的四大组件及应用安装安全问题(4)

    Android的四大组件及组件间通信 如果想对四大组件有深入的了解,那永远不要停留在一些条条干干的SDK API的认识,需要了解他的通讯,他的复用,他的边界问题,这样才会对四大组件有透明的认识. 四大 ...