ejb3.0学习笔记1----无状态bean开发

本文详细介绍了EJB3.0中无状态Session Bean的开发过程,包括仅具有Remote接口和Local接口的Bean。无状态Bean是一个简单的POJO,由EJB3.0容器自动实例化和管理。开发步骤包括定义接口、实现接口并添加注解。客户端通过JNDI查找访问EJB,JNDI名称遵循特定规则。同时,文章还讨论了Local接口和Remote接口的区别以及如何在不同环境下使用。
摘要由CSDN通过智能技术生成

开发只存在Remote 接口的无状态Session Bean
步骤如下:
第一步:要定义一个会话Bean,首先需要定义一个包含他所有业务方法的接口。这个接口不需要任何注释,就像
普通的java 接口那样定义。调用EJB的客户端通过使用这个接口引用从EJB容器得到的会话Bean对象stub。接
口的定义如下:
HelloWorld.java

package com.foshanshop.ejb3;
public interface HelloWorld {
public String SayHello(String name);
}
第二步:实现上面的接口并加入两个注释@Stateless , @Remote

第一个注释定义这是一个无状态会话Bean,第二个注释指明这个无状态Bean的remote接口。在使用这两个注释时需要使用一些EJB的类包.经过上面的步骤一个只存在Remote接口的无状态会话Bean就开发完成。无状态会话Bean是一个简单的POJO(纯
粹的面向对象思想的java 对象),EJB3.0容器自动地实例化及管理这个Bean。下面是HelloWorld会话Bean的实
现代码:
HelloWorldBean.java 。实现类的命名规则是:接口+Bean ,如: HelloWorldBean

package com.foshanshop.ejb3.impl;
import com.foshanshop.ejb3.HelloWorld;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless
@Remote ({HelloWorld.class})
public class HelloWorldBean implements HelloWorld {
public String SayHello(String name) {
return name +"说:你好!世界,这是我的第一个EJB3 哦.";
}
}
HelloWorld会话Bean开发完了 

 

HelloWorld会话Bean发布成功后,接下来介绍客户端如何访问她。
当一个无状态会话Bean发布到EJB容器时,容器就会自动为她创建一个对象stub,并把她注册进容器的JNDI目录,
客户端代码使用她的JNDI名从容器获得他的stub。通过这个stub,客户端可以调用她的业务方法。例子代码如
下:
Test.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import="com.foshanshop.ejb3.HelloWorld, javax.naming.*, java.util.Properties"%>
<%
Properties props = new Properties();

props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
InitialContext ctx;
try {
ctx = new InitialContext(props);
HelloWorld helloworld = (HelloWorld) ctx.lookup("HelloWorldBean/remote");
out.println(helloworld.SayHello("佛山人"));
} catch (NamingException e) {
out.println(e.getMessage());
}
%>

ctx = new InitialContext(props);是设置JNDI访问的环境,本例使用JBoss,所以把环境设为JBoss的上下文环境。
在这里作者要重点说明一下EJB JNDI名称默认的命名规则,命名规则如下:
1> 如果EJB打包进后缀为*.ear 的J2EE 发布文件,默认的JNDI 名称是
访问本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local
访问远程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote
例:EJB HelloWorld打包进名为HelloWorld.ear 的J2EE 应用,访问她远程接口的JNDI 名是:
HelloWorld/HelloWorldBean/remote
2> 如果EJB应用打包成后缀为*.jar 的发布文件, 默认的JNDI 名称是
访问本地接口:EJB-CLASS-NAME/local
访问远程接口:EJB-CLASS-NAME/remote
例: HelloWorld应用打包成HelloWorld.jar 文件,访问她远程接口的JNDI名称是:HelloWorldBean/remote
另外有一点要注意:EJB-CLASS-NAME 是不带包名的,如com.foshanshop.ejb3.impl.HelloWorldBean只需取
HelloWorldBean。
目前网上很多教材获取JNDI名的方式都过时了,如:
HelloWorld helloworld = (HelloWorld) ctx.lookup(HelloWorld.class.getName());
我们把上面的客户端应用打成war 文件。然后把她拷贝到“[jboss安装目录]/server/all/deploy”目录下。如果war
文件的文件名为 EJBTest.war ,我们可以通过http://localhost:8080/EJBTest/Test.jsp访问客户端。

 

 

开发只存在Local 接口的无状态Session Bean

开发只存在Local接口的无状态会话Bean的步骤和上节开发只存在Remote接口的无状态会话Bean的步骤相同,
两者唯一不同之处是,前者使用@Remote 注释指明实现的接口是远程接口,后者使用@Local 注释指明实现的接口
是本地接口。当@Local 和@Remote 注释都不存在时,会话 Bean 实现的接口默认为Local 接口。如果在本机调用
EJB(确保客户端与EJB 容器运行在同一个JVM),采用Local 接口访问EJB 优于Remote 接口,因为Remote接口
访问EJB 需要经过远程方法调用(RPCs)环节,而Local 接口访问EJB 直接从JVM 中返回EJB 的引用。下面是只存
在Local 接口的无状态会话Bean 代码。
LocalHelloWorld.java
//author:lihuoming
package com.foshanshop.ejb3;
public interface LocalHelloWorld {
public String SayHello(String name);
}
LocalHelloWorldBean.java
//author:lihuoming
package com.foshanshop.ejb3.impl;
import javax.ejb.Local;
import javax.ejb.Stateless;
import com.foshanshop.ejb3.LocalHelloWorld;
@Stateless
@Local ({LocalHelloWorld.class})
public class LocalHelloWorldBean implements LocalHelloWorld {
public String SayHello(String name) {
return name +"说:你好!世界,这是一个只具有Local接口的无状态Bean";
}
}
客户端调用代码:
LocalSessionBeanTest.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import="com.foshanshop.ejb3.LocalHelloWorld, javax.naming.*, java.util.Properties"%>
<%
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
InitialContext ctx;
try {
ctx = new InitialContext(props);
LocalHelloWorld helloworld = (LocalHelloWorld)

ctx.lookup("LocalHelloWorldBean/local");
out.println(helloworld.SayHello("佛山人"));
} catch (NamingException e) {
out.println(e.getMessage());
}
%>
上面的客户端代码打包成war文件发布到jboss中。如果你试图在独立的Tomcat服务器中执行客户端代码(如何
在独立的Tomcat环境中调用EJB请考照 第二章:在独立的Tomcat 中调用EJB),你将获得如下例外:
java.lang.NullPointerException
org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalProxy.java:74)
产生此例外的原因是,调用Local接口的客户端与EJB容器不在同一个VM(虚拟内存堆)。相对于发布到jboss
deploy目录下的客户端应用而言,他与EJB容器运行在同一个VM。如果客户端与EJB容器在不同的VM,只能
通过其Remote接口进行访问。

 

开发存在Remote 与Local 接口的无状态Session Bean
在实际应用中,一个无状态Session Bean都应该实现Remote与Local接口。当会话Bean的某些方法只供EJB
容器内部调用而不对外暴露时,可以把他定义在Local接口。本节介绍如何开发一个具有Remote与Local 接口的
无状态Session Bean。开发前先介绍一下两个接口具有的方法,两者都含有方法Add(int a, int b),而Local接口含
有一个自己的方法:getResult()。下面是例子的源代码。
定义远程接口:Operation.java
//author:lihuoming
package com.foshanshop.ejb3;
public interface Operation {
public int Add(int a, int b);
}
定义本地接口:LocalOperation.java,本地接口具有远程接口的所有方法,另外有自己的方法getResult()
//author:lihuoming
package com.foshanshop.ejb3;
public interface LocalOperation extends Operation {
public int getResult();
}
实现本地接口与远程接口的会话Bean:OperationBean.java

//author:lihuoming
package com.foshanshop.ejb3.impl;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import com.foshanshop.ejb3.LocalOperation;
import com.foshanshop.ejb3.Operation;
@Stateless
@Remote ({Operation.class})
@Local ({LocalOperation.class})
public class OperationBean implements Operation, LocalOperation {
private int total = 0;
private int addresult = 0;
public int Add(int a, int b) {
addresult = a + b;
return addresult;
}
public int getResult() {
total += addresult;
return total;
}
}
JSP客户端:OperationBeanTest.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import="com.foshanshop.ejb3.Operation, com.foshanshop.ejb3.LocalOperation,
javax.naming.*, java.util.Properties"%>
<%
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
InitialContext ctx = new InitialContext(props);
try {
Operation operation = (Operation) ctx.lookup("OperationBean/remote");
out.println("通过远程接口调用EJB成功");
out.println("<br>(通过远程接口调用EJB)相加的结果是:"+ operation.Add(1,1));
} catch (Exception e) {
out.println("<br>远程接口调用失败");
}
out.println("<br>==============================================");
Jboss EJB3.0实例教程
版权所有:黎活明
try {
//通过本地接口调用EJB
LocalOperation A = (LocalOperation) ctx.lookup("OperationBean/local");
out.println("<br>(通过本地接口调用EJB)调用A.Add()的结果是:"+ A.Add(1,1));
out.println("<br>调用A.getResult()的结果是:"+ A.getResult());
LocalOperation B = (LocalOperation) ctx.lookup("OperationBean/local");
out.println("<br>(通过本地接口调用EJB)调用B.Add()的结果是:"+ B.Add(1,1));
out.println("<br>调用B.getResult()的结果是:<font color=red>"+ B.getResult() +
"</font>");
} catch (Exception e) {
out.println("<br>本地接口调用失败");
}
%>
把会话Bean及客户端Web应用发布到jboss,客户端的调用结果如下:
通过远程接口调用EJB成功
(通过远程接口调用EJB)相加的结果是:2
==============================================
(通过本地接口调用EJB)调用A.Add()的结果是:2
调用A.getResult()的结果是:2
(通过本地接口调用EJB)调用B.Add()的结果是:2
调用B.getResult()的结果是:4
细心的你可能会发现调用Local接口时,两次累加的结果都不一样,一个是2,一个是4。调用本地接口的客户端
代码片段如下:
//通过本地接口调用EJB
LocalOperation A = (LocalOperation) ctx.lookup("OperationBean/local");
out.println("<br>(通过本地接口调用EJB)调用A.Add()的结果是:"+ A.Add(1,1));
out.println("<br>调用A.getResult()的结果是:"+ A.getResult());
LocalOperation B = (LocalOperation) ctx.lookup("OperationBean/local");
out.println("<br>(通过本地接口调用EJB)调用B.Add()的结果是:"+ B.Add(1,1));
out.println("<br>调用B.getResult()的结果是:<font color=red>"+ B.getResult() +
"</font>");
你可能认为A和B得到的应该是两个不同的对象,根据OperationBean.java 的代码判断,他们的结果都是2才对。
为何一个为2,另一个为4 呢。
这是因为Stateless Session Bean不负责记录使用者状态,Stateless Session Bean一旦实例化就被加进会话池中,各
个用户都可以共用。即使用户已经消亡,Stateless Session Bean的生命期也不一定结束,它可能依然存在于会话池
中,供其他用户调用。如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值