下面我们修改客户端代码来验证一下无状态会话Bean的变量是怎么回事。
服务端代码修改如下,修改后重新打包部署。
package ejb.sessionBean.impl;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.Stateless;
import ejb.sessionBean.Hello;
@Stateless
public class HelloEAOImpl implements Hello {
// 访问次数
private int num;
private Map<String, Integer> buyInfo = new HashMap<String, Integer>();
@Override
public String hello(String name) {
return "欢迎你:" + name;
}
@Override
public int countNum() {
num++;
return num;
}
public void addItem(String item) {
if (buyInfo.containsKey(item)) {
buyInfo.put(item, buyInfo.get(item) + 1);
} else {
buyInfo.put(item, 1);
}
System.out.println("Stateless-buyInfo:" + buyInfo);
}
}
|
测试代码增加几个方法如下
public void test02() throws NamingException {
context = init();
Hello hello = (Hello) context.lookup("HelloEAOImpl/remote");
System.out.println("test02访问" + hello.countNum());
System.out.println("test02访问" + hello.countNum());
System.out.println("test02访问" + hello.countNum());
System.out.println("test02访问" + hello.countNum());
System.out.println("test02访问" + hello.countNum());
}
public void test03() throws NamingException {
context = init();
Hello hello = (Hello) context.lookup("HelloEAOImpl/remote");
System.out.println("test03访问" + hello.countNum());
System.out.println("test03访问" + hello.countNum());
System.out.println("test03访问" + hello.countNum());
System.out.println("test03访问" + hello.countNum());
System.out.println("test03访问" + hello.countNum());
}
public void test04() throws NamingException {
context = init();
Hello hello = (Hello) context.lookup("HelloEAOImpl/remote");
hello.addItem("叶小钗");
hello.addItem("一页书");
}
public void test05() throws NamingException {
context = init();
Hello hello = (Hello) context.lookup("HelloEAOImpl/remote");
hello.addItem("一页书");
}
|
用junit单独先执行test02方法之后再执行test03方法结果如下:
test2:
test02访问1
test02访问2
test02访问3
test02访问4
test02访问5
|
test3:
test03访问6
test03访问7
test03访问8
test03访问9
test03访问10
|
之后单独先执行test04之后再执行test05
test04服务端控制台效果如下:
10:22:56,063 INFO [STDOUT] Stateless-buyInfo:{叶小钗=1}
10:22:56,079 INFO [STDOUT] Stateless-buyInfo:{一页书=1, 叶小钗=1}
|
test05
10:24:03,644 INFO [STDOUT] Stateless-buyInfo:{一页书=2, 叶小钗=1}
|
由此观之,客户端单线程访问EJB容器的时候,对于客户端来说无状态的会话Bean会将实例变量当做类似于静态变量来处理的。无论是几个客户端,总之只要是非多线程并发访问无状态SessionBean的时候,确实该变量类似于容器全局的静态变量。如果有多个并发访问会如何呢?
我们一气呵成走完junit测试用例(运行2遍)服务端控制台如下。
效果如下:
10:29:00,506 INFO [STDOUT] Stateless-buyInfo:{一页书=2, 叶小钗=2}
10:29:00,506 INFO [STDOUT] Stateless-buyInfo:{一页书=3, 叶小钗=2}
10:29:00,538 INFO [STDOUT] Stateless-buyInfo:{一页书=4, 叶小钗=2}
10:29:19,618 INFO [STDOUT] Stateless-buyInfo:{叶小钗=1}
10:29:19,634 INFO [STDOUT] Stateless-buyInfo:{一页书=5, 叶小钗=2}
10:29:19,650 INFO [STDOUT] Stateless-buyInfo:{一页书=6, 叶小钗=2}
|
可以看出此时的buyInfo变量不再是单一静态的了,并发访问的时候,对象池会再生出(new)一个新的实例变量,该实例变量的生命是由应用服务器的对象池来管理的。而客户端调用的时候具体获得和调用哪个实例变量,这个不好说,只能看应用服务的JVM调度了。所以来说很多人建议甚至是规定不要在无状态的SessionBean中定义实例变量,服务端无法维护其通讯状态是这个意思!有状态的会话Bean会记录一次会话调用中,实例变量的状态的实质含义就是说保证在客户端获取、调用有状态的Bean时,保证里面的实例变量和上次访问的时候是一样的、是线程安全的、对于你这个客户端来说是独一无二的!因此有状态的开销也是很大的。无状态的对象池仅仅维护并发所产生的这几个变量罢了,但是我无状态的SessionBean可不能保证你客户端下次访问的就一定是你上次所操作的变量哦………………所以一般在无状态的SessionBean中定义实例变量其实没什么意义,因为客户端真正操作的是哪个实例变量,只有对象池根据并发的实际情况而定,所以很不稳定,所以EJB标准给出的结论就是“不允许”在无状态的SessionBean中定义实例变量。
1. 无状态的会话Bean的本地、远程调用
EJB组件都会分为本地调用(local)和远程调用(remote)2种。
1)一般客户端程序无论是手机、ATM机、电信的终端设备、web服务器的调用会话Bean的时候都是调用的在另一个地理位置的远程EJB容器中的SessionBean。此时就需要远程调用remote。在接口的类名上加入@Remote注解就可以了。
2)在EJB容器内部,EJB组件和EJB组件进行相互调用的时候,那么本身就是“兄弟联”内部的,好说话。此时只需要本地的local方式调用就可以了。在接口的类名上加入@Local注解就可以了。在本地调用的时候其实就是保证在同一个JVM上运行就可以了。
2. 会话Bean的发布
上面提到了SessionBean的打包,下面我们来个截图看看,笔者用的是MyEclipse8.6。打包过程如下
在开发EJB项目右键,export
选中EJB的接口和实现类,导出后是一个jar,将此jar包拷贝到${JBOSS_HOME} \server\default下面即可完成EJB的发布。
注:如果EJB调用到了辅助类,此辅助类也需要打包到jar中。还有就是客户端调用此EJB接口的时候,切记接口的包结构一定要和服务端的包结构一致。
- 大小: 76.1 KB
分享到:
相关推荐
### JavaEE5学习笔记07-Web层与EJB集成总结 #### 一、JavaEE5框架中的Web层与EJB集成概述 在JavaEE5(即Java Platform, Enterprise Edition 5)中,Web层与EJB(Enterprise JavaBeans)的集成是构建企业级应用的...
在JavaEE环境中,RMI经常与EJB结合使用,尤其是无状态SessionBean,因为它们不需要维持客户端的会话状态,适合RMI的轻量级通信模式。 当一个EJB被标记为远程接口时,它可以通过RMI在不同 JVM(Java Virtual ...
"javaee思维导图版笔记-吉林大学" 本笔记主要涵盖了Java EE的基础知识,包括Servlet、JSP、JNDI、JPA等方面的内容。 一、Servlet概述 Servlet是Java EE中的一种服务器端组件,用于处理HTTP请求并返回响应。...
- **会话Bean**:在整个用户会话期间保持,用于跟踪用户状态。 - **应用Bean**:在整个应用程序范围内共享,用于全局数据。 **自定义标签(Custom Tags)**提供了一种扩展JSP语法的方式,通过定义标记库描述符(TLD...
包括会话Bean(Session Beans)负责业务逻辑,实体Bean(Entity Beans)作为持久化对象,以及消息驱动Bean(Message-Driven Beans)处理JMS消息。 6. **JMS (Java Message Service)**:JMS允许应用程序之间异步通信...
Java/JavaEE 学习笔记 作者在杰普学习时的学习笔记,是J2ee初学者必备手册,是大家学习J2EE开发的很好的参考笔记。 Java/JavaEE 学习笔记 内容目录: Unix 学习笔记..........7 一、Unix前言............7 二、...
EJB是JavaEE的核心,提供了三种类型的Bean:会话Bean(Session Beans)处理业务逻辑,实体Bean(Entity Beans)代表持久化数据,消息驱动Bean(Message-Driven Beans)处理消息队列。Spring框架则以其依赖注入和面向...
分为会话Bean(Session Beans)、实体Bean(Entity Beans)和消息驱动Bean(Message-driven Beans),分别处理业务逻辑、持久化数据和消息通信。 5. **JMS(Java Message Service)**:JMS是JavaEE的消息中间件接口...
第四章 Session Bean(会话Bean).....322 第五章 消息驱动Bean(MDB).........327 EJB3.0.....329 第一章 EJB3.0 Foundation...............329 第二章 Session Bean........................330 第三章 消息驱动Bean...
- **EJB(Enterprise JavaBeans)**:分为会话Bean(Session Beans)、实体Bean(Entity Beans)和消息驱动Bean(Message-driven Beans),用于实现业务逻辑和持久化数据。 - **JPA(Java Persistence API)与ORM*...
EJB是Java企业级应用的组件模型,分为会话bean、实体bean和消息驱动bean。它们提供了一种在分布式环境中构建可复用的、事务处理的服务器端组件的方法。虽然现代JavaEE应用更多采用轻量级框架如Spring,但了解EJB的...
EJB分为三种类型:会话bean(Session Beans)处理客户端请求,实体bean(Entity Beans)代表持久化的业务对象,消息驱动bean(Message-Driven Beans)用于处理JMS消息。 4. **JMS**:Java Message Service允许在...