ejb三种bean之会话bean

会话bean(session bean),可以分为无状态会话bean和有状态会话bean

  负责与客户端交互,是编写业务逻辑的地方,在会话bean中可以通过jdbc直接操作数据库,但大多数情况下都是通过实体bean来完成对数据库的操作.

•无状态会话bean

 平常,我们使用最多的是无状态bean,因为它的bean实例可供多个用户使用,所以它的性能比有状态bean高.正因为一个bean实例被多个用户使用.那么,前一个用户设置的值有可能被后一个用户所修改,所以它无法正确保存某个用户设置的值,因此是无状态的.

•有状态会话bean

有状态bean平常使用的并不多,因为它的一个bean实例只供一个用户使用,所以性能开销比较大,正因为它的实例只被一个用户使用,用户为它设置的值是不会被其他用户修改,所以可以正确保存用户设置的值,因此是有状态的.

如何开发一个无状态会话bean?

 1.可以在jboss安装路径的client目录下找到,通常会把client目录下的所有jar文件添加到项目的类路径下.

2.开发接口和实现类:

•接口(接口可以是远程接口或本地接口)
public interface HelloWorld {
public String sayHello(String name);
}
•实现类
@Stateless
@Remote(HelloWorld.class)

public class HelloWorldBean implements HelloWorld {
@Override
public String sayHello(String name) {
return name+"说:你好啊!";
}
}
把以上打包成jar,然后将打好的jar放到default这个配置项的deploy目录下面,就将这个ejb发布了.jboss就可以自动对它进行部署了
ejb在软件开发的分层中它属于业务层,通常它是需要被客户端进行调用的.MVC中想想,这个客户端可以是jse,jme等.

会话bean的客户端:

public class EJBClient {
public static void main(String[] args) {
try {
InitialContext ctx = new InitialContext();
HelloWorld helloworld = (HelloWorld) ctx
.lookup("HelloWorldBean/remote");//参数里面的是JNDI名称
System.out.println(helloworld.sayHello("张三"));
} catch (NamingException e) {
System.out.println(e.getMessage());
}
}
}

重要的几点:

1.在进行JNDI查找前,我们必须设置应用服务器的上下文信息,主要是设置JNDI驱动的类名(java.naming.factory.initial)和命名服务提供者的URL (java.naming.provider.url) 。

如同数据库一样,根据访问命名服务器的不同,为上下文设置的驱动类和URL也是不同的

创建InitialContext对象时如果没有指定Properties参数,InitialContext还会在classpath下寻找jndi.properties文件,并从该文件中加载应用服务器的上下文信息。这样避免了硬编码为InitialContext设置Properties参数。

jndi.properties的配置如下:(这个是用作为jboss应用服务器的上下文信息)

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

java.naming.provider.url=localhost:1099

java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

2.

当EJB发布到Jboss 时,如果我们没有为它指定全局JNDI名称或修改过其默认EJB名称,Jboss就会按照默认的命名规则为EJB生成全局JNDI名称,默认的命名规则如下:

如果把EJB作为模块打包进后缀为*.ear的JAVA EE企业应用文件,默认的全局JNDI名称是

l本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local
l远程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote

      EAR-FILE-BASE-NAME为ear文件的名称,EJB-CLASS-NAME为EJB的非限定类名。

例:把HelloWorld应用作为EJB模块打包进名为HelloWorld.ear的企业应用文件,它的远程接口的JNDI 名称是:HelloWorld/HelloWorldBean/remote

如果把EJB应用打包成后缀为*.jar的模块文件,默认的全局JNDI名称是

l本地接口:EJB-CLASS-NAME/local
l远程接口:EJB-CLASS-NAME/remote

例:把HelloWorld应用打包成HelloWorld.jar文件,它的远程接口的JNDI名称是:HelloWorldBean/remote

可以使用注释改变会话Bean的JNDI 名称

如果我们没有指定EJB的JNDI名称,当EJB发布到应用服务器时,应用服务器会按默认规则为EJB生成全局JNDI名称。当我们需要自定义JNDI名称时,可以这样做

如果EJB在Jboss中使用,可以使用Jboss提供的 @LocalBinding 和 @RemoteBinding 注释,@LocalBinding注释指定Session Bean的Local接口的JNDI名称,@RemoteBinding注释指定Session Bean的Remote接口的JNDI名称,如下:

@Stateless

@Remote ({Operation.class})

@RemoteBinding (jndiBinding="foshanshop/RemoteOperation")

@Local ({LocalOperation.class})

@LocalBinding (jndiBinding="foshanshop/LocalOperation")

public class OperationBean implements Operation, LocalOperation {

}

也可以使用xml部署描述文件改变SessionBean的JNDI 名称

由于JNDI名称与厂商有关,如果使用注释定义JNDI名称会带来移植问题,因此建议使用ejb-jar.xml部署描述文件进行定义,该文件必须放置在jar的META-INF目录下

<?xml version="1.0"encoding="UTF-8"?>

<ejb-jar  xmlns=http://java.sun.com/xml/ns/javaee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

                         http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"  version="3.0">

<enterprise-beans>

 <session>

   <ejb-name>HelloWorldBean</ejb-name>

   <mapped-name>HelloWorldBean</mapped-name>

 </session>

</enterprise-beans>

</ejb-jar>

ejb-name为EJB名称,mapped-name为bean的JNDI名称。目前jboss不支持在ejb-jar.xml通过mapped-name指定JNDI名称,但我们可以使用他专属的部署描述文件jboss.xml进行定义,如下:

<?xml version="1.0"encoding="UTF-8" ?>

<!DOCTYPE jboss PUBLIC "-//JBoss//DTDJBOSS 4.2//EN“ "http://www.jboss.org/j2ee/dtd/jboss_4_2.dtd">

<jboss><enterprise-beans> <session>

     <ejb-name>HelloWorldBean</ejb-name>

    <jndi-name>hello/remote</jndi-name>

</session></enterprise-beans></jboss>

具有Local接口的Session bean

首先了解一下通过远程接口调用ejb的过程,首先客户端需要与ejb建立起socket通信,在通信管道上他们之间需要来回发送IIOP协议消息,因为数据要在网络进行传输,存放数据的java对象必须要进行序列化。


在这个过程中我们看到,有网络通信的开销、协议解析的开销、对象序列化的开销。因为ejb是分布式技术,它允许客户端与ejb应用在不同一机器上面,所以这些性能开销也是必然的。但是在实际生产中,不可避免存在这种情况:客户端与EJB应用运行在同一个jboss中。这时候客户端访问ejb是否有必要走上面的网络通信呢?据我们所知,这时候客户端与ejb是在同一个jvm内,他们之间完全可以通过内存进行交互,这样就可以避免网络通信的性能开销。既然我们都想到了这一点,EJB专家组也想到了这一点,所以引入了本地接口。通过本地接口调用ejb,直接在内存中交互,这样就能避免因网络通信所造成的各种性能开销。但是有一点,大家必须注意,只有客户端与EJB应用在同一个JVM内运行的时候,我们才能调用本地接口,否则只能调用远程接口。谈到这里,有同学会问什么情况下客户端与EJB应用是在同一个JVM?简单地说只要客户端与ejb发布在同一个jboss内,我们就认为他们是在同一个JVM

@Stateless

@Local ({HelloWorldLocal.class})

public class HelloWorldBean implements HelloWorldLocal {

   public String say (String name) {       

        return name +"说:你好!世界,这是我的第一个EJB3哦.";

   }

}

如何访问具有本地接口的会话bean呢?

新建一个web项目,在jsp里面进行访问 ,然后打好war包,把打好的war包放到jboss的default/deploy目录下面,这样确保客户端与EJB应用运行在同一个jboss中

<%@ page import="cn.itcast.ejb3.HelloWorldLocal, javax.naming.*, java.util.Properties"%>

<%

try {

  InitialContext ctx = new InitialContext();

  HelloWorldLocal helloworld = (HelloWorldLocal) ctx.lookup("HelloWorldBean/local");

  out.println(helloworld.sayHello("佛山人"));

} catch (NamingException e) {

  out.println(e.getMessage());

}

%>

然后访问这个jsp页面即可

一般做应用的时候是既做一个本地接口,也做一个远程接口如果客户端应用与ejb部署在同一个jboss内的话,会优先应用本地接口,否则用远程接口.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章