A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 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应答消息解析成返回值。




0 个回复

您需要登录后才可以回帖 登录 | 加入黑马