JavaEE5学习笔记05-EJB之会话Bean(sessionBean)总结-----2

下面我们修改客户端代码来验证一下无状态会话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)和远程调用(remote2种。

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 接口的时候,切记接口的包结构一定要和服务端的包结构一致。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值