本帖最后由 li745547 于 2018-3-25 13:21 编辑
使用xml文件改变Session Bean的JNDI 名称 由于JNDI名称与厂商有关,如果使用注释定义JNDI名称会带来移植问题,因此建议使用ejb-jar.xml部署描述文件进行定义,该文件必须放置在jar的META-INF目录下 Xml代码 [url=][/url]
- <?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代码 [url=][/url]
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 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>
项目中使用: Java代码 [url=][/url]
- public interface ControlService {
-
- void init();
- }
-
- @Stateless (name = "ControlService")
- @Local ({ControlService.class})
- public class ControlServiceImpl implements ControlService{
-
- private static final Logger logger = LoggerFactory.getLogger(ControlServiceImpl.class);
-
- @PersistenceContext
- private EntityManager em;
-
- @Override
- public void init() {
- ...
- }
- ...
- }
META-INF下: jboss.xml: Xml代码 [url=][/url]
- <?xml version="1.0" encoding="UTF-8"?>
- <jboss>
- <enterprise-beans>
- <session>
- <ejb-name>ControlService</ejb-name>
- <jndi-name>ESBDaemon/ControlService</jndi-name>
- <local-jndi-name>ESBDaemon/ControlService/local</local-jndi-name>
- </session>
-
- ..
- </enterprise-beans>
- </jboss>
persistence.xml: Xml代码 [url=][/url]
- <?xml version="1.0" encoding="UTF-8"?>
- <persistence xmlns="http://java.sun.com/xml/ns/persistence"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
- version="1.0">
- <persistence-unit name="init-ds">
- <!-- 数据源:server\default\deploy\datasources\visesbdb-ds.xml 中jndi-name为datasources/visesbdb -->
- <jta-data-source>java:/datasources/visesbdb</jta-data-source>
- </persistence-unit>
- </persistence>
通过远程接口调用ejb的过程: 首先客户端需要与ejb建立起socket通信,在通信管道上他们之间需要来回发送IIOP协议消息,因为数据要在网络进行传输,存放数据的java对象必须要进行序列化。 在这个过程中我们看到,有网络通信的开销、协议解析的开销、对象序列化的开销。因为ejb是分布式技术,它允许客户端与ejb应用在不同一机器上面,所以这些性能开销也是必然的。但是在实际生产中,不可避免存在这种情况:客户端与EJB应用运行在同一个jboss中。这时候客户端访问ejb是否有必要走上面的网络通信呢?据我们所知,这时候客户端与ejb是在同一个jvm内,他们之间完全可以通过内存进行交互,这样就可以避免网络通信的性能开销。既然我们都想到了这一点,EJB专家组也想到了这一点,所以引入了本地接口。
通过本地接口调用ejb,直接在内存中交互,这样就能避免因网络通信所造成的各种性能开销。但是有一点,大家必须注意,只有客户端与EJB应用在同一个JVM内运行的时候,我们才能调用本地接口,否则只能调用远程接口。 什么情况下客户端与EJB应用是在同一个JVM?简单地说只要客户端与ejb发布在同一个jboss内,我们就认为他们是在同一个JVM
开发具有local接口session bean: Java代码 [url=][/url]
- @Stateless
- @Local ({HelloWorldLocal.class})
- public class HelloWorldBean implements HelloWorldLocal {
-
- public String say (String name) {
- return name +"说:你好!世界,这是我的第一个EJB3哦.";
- }
- }
-
-
- try {
- InitialContext ctx = new InitialContext();
- HelloWorldLocal helloworld = (HelloWorldLocal) ctx.lookup("HelloWorldBean/local");
- out.println(helloworld.sayHello("佛山人"));
- } catch (NamingException e) {
- out.println(e.getMessage());
- }
EJB调用机制 由于EJB的调用过程对开发者来说是透明的,以至于我们错误地认为:lookup()方法返回的对象就是bean实例。实际上,客户端与Session bean交互,它并不直接与Bean实例打交道,而是经由bean的远程或本地接口。当你调用远程或本地接口的方法时,接口使用的是存根(stub)对象。该存根实现了sessionbean的远程或本地接口。它负责将方法调用经过网络发送到远程EJB容器,或将请求路由到位于本地JVM内的EJB容器。存根是在部署期间使用JDK所带的java.lang.reflect.Proxy动态生成。
第一步:客户端调用远程接口的SayHello()方法(实际上调用的是存根对象的SayHello()方法,该存根实现了HelloWorld的远程接口)。 第二步:方法调用经过IIOP Runtime被转换成CORBA IIOP消息发往应用服务器。 第三步:应用服务器接收到请求消息后,交由骨架(skeleton)处理。骨架通过IIOP Runtime解析协议消息,并根据协议要求调用bean实例的SayHello()方法。 第四步:骨架(skeleton)将SayHello()方法的返回值经过IIOP Runtime转换成CORBA IIOP应答消息发回客户端。 第五步:存根对象通过IIOP Runtime将CORBA IIOP应答消息解析成返回值。
|