24小时热门版块排行榜    

查看: 513  |  回复: 4
当前主题已经存档。

wswswws

银虫 (正式写手)

[交流] 【活动3】EJB技术简介

EJB技术简介

EJB的全称是Enterprise java bean。是JAVA中的商业应用组件技术。EJB结构中的角色 EJB 组件结构是基于组件的分布式计算结构,是分布式应用系统中的组件。一个完整的基于EJB的分布式计算结构由六个角色组成,这六个角色可以由不同的开发商提供,每个角色所作的工作必须遵循Sun公司提供的EJB规范,以保证彼此之间的兼容性。这六个角色分别是EJB组件开发者(Enterprise Bean Provider) 、应用组合者(Application Assembler)、部署者(Deployer)、EJB 服务器提供者(EJB Server Provider)、EJB 容器提供者(EJB Container Provider)、系统管理员(System Administrator)。

[ Last edited by 幻影无痕 on 2006-11-18 at 07:40 ]
回复此楼
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

cremaster

银虫 (小有名气)

0.5

★ ★ ★ ★ ★ ★ ★ ★
yuefour(金币+8):谢谢补充讨论,3个补充贴给你加一起了,^_^
什么是EJB
引用回帖:
1.什么是 EJB?
一个技术规范:EJB 从技术上而言不是一种"产品"
EJB 是一种标准描述了构建应用组件要解决的:
可扩展 (Scalable)
分布式 (Distributed)
事务处理 (Transactional)
数据存储 (Persistent)
安全性 (Secure)

2.Sun 对 EJB 的期望
提供一个标准的分布的、基于 OO 的组件架构
屏蔽复杂的系统级功能需求
Write once, run anywhere
与非 Java 应用之间的互操作能力
兼容 CORBA 标准

3.为什么选择 EJB?

EJB 服务器完成"繁杂"的工作:应用开发人员关注于业务逻辑的实现而不是底层的实现机制(类似于 4GL 语言设计的目标)
支持事务处理
多个业务操作同时成功,或全部失败
可以通过在代码外的描述来定义事务处理级别
可扩展性
EJB 可以根据您应用的增长而扩展
EJB 服务器往往还提供了负载均衡和
安全性:由 EJB 服务器提供资源的访问权限控制

4.EJB 架构

为了满足架构的目标,规范中描述了
服务器 (Server)
容器 (Container)
类 (Class) 和实例 (Instance)
Home 和 Remote 接口
客户端 (Client)

5. 简化的编程模型

关注于业务逻辑实现:EJB 负责生命周期 (lifecycle), 数据存储 (persistence), 事务处理语义 (transactional semantic), 安全(security), ...
通用的编程模型:各种服务的高层 API
Java 是其编程语言

1.EJB 特点

由一个 EJB 容器在运行时创建和管理 EJB
在部署 EJB 时定制其运行方式
由 EJB 容器和服务器来协调客户端的访问
可以部署到任何兼容的 EJB 容器中
客户端对 EJB 的视图是由 Bean 开发人员决定的

2.EJB 服务器

管理 EJB 容器 (它管理 Bean)
提供对操作系统服务的存取
提供 Java 相关的服务,尤其是
通过 JNDI 访问命名空间
基于 OTS 的事务处理服务

3.EJB 容器

管理 Bean 生命周期:将 EJB 服务器提供的服务传递给 Bean
生成代码来实现对 Bean 的存取访问
强制事务处理的限制
创建、初始化和回收 Bean
管理持久数据的存储
对客户端而言 EJB 容器是透明的

4.在一个 EJB 服务器中的容器

目前容器通常是由 EJB 服务器本身提供的
在 EJB 1.0 或 1.1 规范中没有定义容器-到-服务器的接口
各厂商可以根据他们的见解来实现服务器和容器的各自责任

5.容器提供服务: 数据存储

容器决定何时载入/储存状态
Container-Managed Persistence(容器管理存储/CMP)
容器负责存储您的 Bean
容器生成必要的类和代码
Bean-Managed Persistence(Bean 管理存储/BMP)
Bean 开发人员提供存储代码
开发人员决定 如何存储, 容器仍然决定 何时进行

6.容器提供服务: 事务处理

可以由容器代理来实现
容器将得到业务逻辑方法的事务处理需求
容器提供事务控制代码
也可以由程序员通过代码实现

7.容器提供服务: 其它服务

其它服务包括
命名 (Naming)
安全 (Security)
线程管理 (Thread management)
这些服务由容器代理完成将减少应用开发人员的负担


8.分布式对象运算

远程对象被作为本地对象来处理:传递信息的方式不变,但开销更大
Enterprise JavaBeans 永远运行在服务器上:对 Bean 的访问永远是远程调用

9.Stub 和 Skeleton

由 EJB 生成:
"Stub" 对要传递出去的信息编码
"Tie/Skel" 将接受到的信息解码并传递给目标对象

10.分类: Enterprise JavaBeans

+---Entity Beans--CMP/BMP
Ejb--|
+---Session Beans--Stateful/Stateless

会话 Bean (Session Bean):根据 EJB 规范,一个会话 Bean 是:

代表单个客户端来执行
可以参与到事务处理中
不直接代表共享于数据库中的数据,但它能访问和更新这些数据
相对而言是短暂存在的
当 EJB 容器失效后就不存在---客户端需要重新建立一个信新的会话对象来继续运算

实体 Bean (Entity Bean):根据 EJB 规范,一个实体 Bean 是:

提供在数据库中数据的对象视图
允许被多个用户共享存取访问
可以是长期存在 (只要它存在于数据库中)
实体 Bean, 它的主键对象, 以及它的远程引用将能跨 EJB 容器的宕机而存在

11.EJB 类和实例

构建 EJB 应用包括来自三方的代码
开发人员编写的代码
由 EJB API 定义的类和接口
由容器自动生成的代码
开发人员编写的代码包括
Bean 类 (定义了业务逻辑)
Home 接口 (如何查找或创建 bean)
Remote 接口 (如何存取 bean)
其它组件,根据 bean 实际要求

12.EJB Home 接口

每个 bean 有一个
用于:创建新的 bean 实例、查找现存的 bean (只能是实体 bean)

Remote 接口:定义 bean 的公共接口---只有在 Remote 接口中定义的方法才能被客户端访问

EJB 客户端

可以为 servlet, JSP, 应用程序或其它 bean
通过 JNDI 来查找 EJB home 接口,步骤为:
创建一个 JNDI Context (initial context)
使用 JNDI Context 来查找 bean home 接口
使用 bean home 接口来创建/查找 bean 实例
使用 bean 实例完成业务操作
实际的存取 (对 EJB) 是通过容器生成的类来完成

EJB 架构

客户端对 bean 访问永远不是直接的
EJBObject (tie) 是由容器自身提供的:用来帮助管理 bean 的生命周期

EJB 中的角色

EJB 服务器供应商: 开发并销售 EJB 服务器
EJB 容器供应商: 开发并销售 EJB 容器
Enterprise bean 开发人员: 开发并销售 EJB
应用组装人员: 将不同的 EJB 搭建成应用
部属人员: 使用相应工具在运行环境下配置 EJB
系统管理员: 监视运行时情况

***************
*您学到了哪些?*
***************
EJB 是构建健壮,可扩展并支持事务处理的分布式对象技术规范
有两种类型的 EJB: Session Bean 和 Entity Bean
一个 EJB 服务器使用 EJB 容器;容器来管理其所包容 bean 的生命周期
每个 bean 将有三个类: bean 类, home 接口和 remote 接口

2楼2005-07-02 23:36:57
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

cremaster

银虫 (小有名气)

EJB的入门教材
引用回帖:
1、EJB的开发

先泛泛而论,讲一讲EJB的开发步骤。

1.1 SessionBean的开发
第一步, 写远程接口(remote interface),继承EJBObject接口,把需要调用的public方法写在里面(这些方法将在SessionBean中实现),注意要声明throws java.rmi.RemoteException。
例如:

package jsper.ejb;

import java.rmi.*;
import javax.ejb.*;

public interface MyEJB extends EJBObject
{

public String sayHello() throws java.rmi.RemoteException;

}

第二步, 写Home接口(生成EJBObject引用的factory)
至少生成一个create方法, 注意要声明throws java.rmi.RemoteException和javax.ejb.CreateException。
比如:



package jsper.ejb;

import java.rmi.*;
import javax.ejb.*;


public interface MyEJBHome extends EJBHome
{

MyEJB create() throws java.rmi.RemoteException, javax.ejb.CreateException;

}

第三步, 写真正的Session Bean的实现(实现定义在远程接口中的方法), 需要实现javax.ejb.SessionBean接口
注意:不能用implents MyEJB的方式直接实现远程接口,此处不用抛出RemoteException
package jsper.ejb;

import java.rmi.RemoteException;
import javax.ejb.*;
public class MyEJBClass implements SessionBean {


  public MyEJBClass() {
  }
  //定义在SessionBean 中的方法
  public void ejbCreate() throws RemoteException, CreateException {
  }

  public void ejbActivate() throws RemoteException {
  }

  public void ejbPassivate() throws RemoteException {
  }

  public void ejbRemove() throws RemoteException {
  }

public void setSessionContext(SessionContext ctx)
throws RemoteException {

  }

  //此处是具体的实现

  public String sayHello()

  {

   System.out.println("Hello";
  }
}
第四步,写一个发布用的配置文件ejb-jar.xml
需要提供的信息:
Bean Home name -- The nickname that clients use to lookup your bean's home object.
Enterprise bean class name -- The fully qualified name of the enterprise bean class.
  Home interface class name
  Remote interface class name
Re-entrant -- Whether the enterprise bean allow re-entrant calls. This setting must be false for session beans(it applies to entity beans only)
  stateful or stateless
  Session timeout -- The length of time (in seconds) before a client should time out when calling methods on your bean.
最后你还可以提供属于自己的配置信息供自己控制EJB的工作方式。

例子:

helloEjb
com.jsper.ejb.MyEJBHome
com.jsper.ejb.MyEJB
com.jsper.ejb.MyEJBClass
Stateless
Container



第五步,将你的所有文件用jar工具生成jar文件

ejb-jar.xml须在顶级的META-INF子目录
这句话比较咬嘴, 举个例子

mylib----META-INF--*.XML
|
|com--coucouniu--ejb---EJBClass
    |-EJBHome
    |-EJB

在生成.jar文件时

sh>cd mylib  //注意此处所在目录
sh>jar cv0f myejb.jar *

请注意: 到这一步我们做出的东西都是和和特定的EJB Server是无关的, 只是和遵循EJB的标准有关

第六步,使用特定平台的发布工具生成发布使用的jar文件。
不同的中间件产品此步骤非常不同, 产生的结果都是生成只有自己的EJB Server能理解的远程接口和Home接口实现等等东西,打包在一个jar文件中
一般是很简单的
第七步,把.jar文件发布到EJB Server

根据不同的中间件产品此步骤非常不同, 可以分为启动时发布和运行时发布两种,一般是很简单的, 以weblogic为例:
1、在weblogic.properties 文件中配置使weblogic 启动时自动装载。
添加一个条目比如:
weblogic.ejb.deploy=C:/weblogic510/myserver/ejb_basic_beanManaged.jar,\
   C:/weblogic510/myserver/ejb_basic_test.jar

2、使用deploy或DeployerTool动态装载/卸载/更新

第八步,写客户端的程序(我迄今为止的理解)
在我们使用发布工具把EJB发布到EJB Container的过程中,会绑定一个名字到Container的目录服务中,现在我们要调用时从这个目录服务中把EJBHome对象取出, 这里分为从本地和外部两种情况:
一种是客户端本地调用EJB。 比如和EJB引擎和Servlet引擎是整合在同一个Application Server中, 这时当一个Servlet要调用EJB时无须验证,即可得到EJBHome接口的实现
  Context ic = new InitialContext();
    System.out.println("Looking for the EJB published as 'hello'";
    com.jsper.ejb.MyEJBHome homeInterface = (com.jsper.ejb.MyEJBHome) ic.lookup(“hello”); //发布时绑定的名字是hello
  这样就可从目录服务中得到Home接口的实现, 也是我们最常用的方式, 可移植性很好

外部调用的话首先要经过身份验证,
比如Oracle8i :

String ejbUrl = "sess_iiop://localhost:2481:ORCL/test/MyEJB";
   String username = "scott";
   String password = "tiger";

   // Setup the environment
   Hashtable environment = new Hashtable();
   // Tell JNDI to speak sess_iiop
   environment.put(javax.naming.Context.URL_PKG_PREFIXES, "oracle.aurora.jndi";
   // Tell sess_iiop who the user is
   environment.put(Context.SECURITY_PRINCIPAL, username);
   // Tell sess_iiop what the password is
   environment.put(Context.SECURITY_CREDENTIALS, password);
   // Tell sess_iiop to use credential authentication
environment.put(Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN);
// Lookup the URL
   com.jsper.ejb.MyEJBHome homeInterface = null;
   try {
    System.out.println("Creating an initial context";
    Context ic = new InitialContext(environment);
    System.out.println("Looking for the EJB published as 'test/MyEJB'";
    homeInterface = (com.jsper.ejb.MyEJBHome) ic.lookup(ejbUrl);
   }
   catch (ActivationException e) {
    System.out.println("Unable to activate : " + e.getMessage());
    e.printStackTrace();
    System.exit(1);
   }
再比如weblogic的调用方式:
try
{
   // Get an InitialContext
   String url="t3://localhost:7001";
   Properties h = new Properties();
   h.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory";
   h.put(Context.PROVIDER_URL, url);

Context ctx = new InitialContext(h);

   System.out.println("Getting the EJBHome object…";
    com.jsper.ejb.EJBHome tmp= (com.jsper.ejb.EJBHome)ctx.lookup("hello";

//create three element array of COUNT object
   EJB ejb =tmp.create();
   System.out.println(ejb.sayHello());
}
catch(Exception e)
{
e.printStackTrace();
}
由于和具体的目录服务、协议相关,为了达到可移植的目的,只好多做一些工作,幸好一般不需要做这些工作。

3楼2005-07-02 23:38:56
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

cremaster

银虫 (小有名气)

理解EJB的参数传递
引用回帖:
Understanding EJB argument passing
Scott Oaks
Scott Oaks is a Systems Engineer for Sun Microsystems, where he focuses on practical applications of Java technology. He is the co-author, with Henry Wong, of Java Threads.


TODAY´S TIP REGARDS a performance characteristic that is particularly important to certain Enterprise JavaBean (EJB) applications, although it has applicability to other types of Java applications as well. It revolves around the way in which EJBs (and, more generally, any distributed object system) pass arguments to each other; I´ll discuss how this task is accomplished and when you might want to change the manner in which it is done.
First, some terminology and a brief review. For the most part, arguments that are passed between two Java methods are passed by value. If you are given the code



int i = 3;
someMethod(i);

after invoking someMethod(), we know i will have the value 3, no matter what happens inside the method invocation. i is passed by value. If you are given the code


Point p = new Point(3, 3);
someOtherMethod(p);

after invoking someOtherMethod(), we know p will reference the same object it referenced before the method invocation?the memory location it points to is the same. But the contents of that memory may have changed. If the method calls its parameter q and executes the statement q.x = 4, then when the method returns, p will refer to the point with coordinates (4, 3). In this case, p is passed by reference.
I´ve had semantic arguments with developers who insist that because p points to the same memory location all along, it too is passed by value. If the method executes the statement q = new Point(4, 3), then when the method returns, p will refer to the original point, which will still have the coordinates (3, 3). No matter what you choose to call it, this is the way Java works.

The point is that the contents of an object can change when it is passed between methods in Java. The exception to this rule occurs with RMI and other distributed programming technology. In that case, the two methods in question are running on two different virtual machines. To get the object from one method to another, the object is serialized by the client and deserialized by the server. A side effect of this deserialization is that a copy of the object has been made, and no matter what changes are made to the contents of that object in the server, the contents of that object on the client will not change. In this case, the objects are said to be passed by value (though in those semantic wars, some prefer the term "passed by copy".

This difference in programming semantics takes a little getting used to, but it has a rationale. Clearly, a copy of the object has to be made in the server´s virtual machine as it cannot share physical memory with the client´s virtual machine. The standard Java object semantics could have been preserved if the copy of the object was sent back to the client and somehow overlaid in memory on top of the original object. Such a trick would have been complex and would often have had a severe impact on performance. If the object hasn´t changed, it´s a waste of time to copy it back. It´s far better for developers to be in control of any data that needs to be sent back to the client (and to send it, for example, in the return object).

This brings us to EJBs: a method invocation on an EJB is an RMI call. It is a requirement of the EJB specification that parameters passed during the method call be passed by value so that the EJB receives a copy of any object parameters (and the caller receives a copy of the return object, if applicable). Thus, your EJB client can assume that the contents of an object passed to an EJB server are not changed by the server.

As it turns out, EJBs that call each other are often deployed within the same virtual machine. Think of a session bean that needs to use multiple entity beans?all of the beans are often deployed within the same virtual machine. In this case, the object serialization is not strictly necessary. The client and server both have reference to the original object. But if the server (the entity bean) changes the contents of the parameter object, the client (the session bean) will see those changes. Later, if for scaling (or other) reasons the entity beans are moved onto a different machine, the session beans will no longer see any changes to the content of the parameter object. It would be untenable to have different semantics depending on how the application is deployed; that is why all parameters between EJBs are always passed by value, even when they are within the same virtual machine.

Most application servers are aware of the performance penalty paid by making an unnecessary copy of the object passed between EJBs within the same virtual machine and have an option that can be set to have these objects passed by reference (thereby avoiding the copy). If you turn on that option for an arbitrary EJB application, it is possible that the application will break. If the application is written to assume pass-by-value semantics, then the unexpected change in data contents could have a detrimental effect.

On the other hand, if you write your EJBs so that they make no assumption about these semantics, then you´re ahead of the game. You can gain the performance benefit from passing by reference when the EJBs are deployed within the same virtual machine, and you can still safely deploy them on multiple machines. What this means is that the EJB must never modify any object it receives as a parameter. If it returns an object, it must return a new instance of the object so that it is not inadvertently shared.

The feasibility of this will depend, of course, on your application. I´ve seen EJB applications where enabling pass-by-reference semantics produced a 25% benefit, so if you have an application that makes a large number of EJB calls within the same virtual machine, a little forethought in application design might be to your benefit.

4楼2005-07-02 23:41:43
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

cremaster

银虫 (小有名气)

提高EJB性能的十大技巧
引用回帖:
EJB调用是耗时、费力的。怎么提高EJB的性能?我们为解决这一问题,开始边写边讨论。等到完成了,我才发现,我们所应用的技巧总结一下,竟有十条。把提高EJB性能的这些技巧总结一下,为以后的项目做参考。

1.用一个Session Bean封装多个Entity Bean,将原来的多个Entity Bean的Remote调用和Local调用封装在一个Session Bean中。所以建立一个ServerFacade,它为多个对象提供统一获取EJB Home和获取对象的接口。ServerFacade为程序要用到的所有EJB的home handle提供缓存,提高访问JNDI Name的时间,达到提高访问效率的目的。以后查找JNDI Name的方法都应写在接口里,调用时直接从接口调用。

2.在EJB的Remote接口中使用粗粒度的方法,不推荐使用细粒度方法。

3.如果EJB的Remote接口获取成功,应不再使用Remote接口,而是将Remote接口构造成一个一般的JAVA对象,通过调用一般的JAVA对象的方法来达到减少对网络的访问。

4.如果你部署EJB客户端和EJB在相同的JVM上,建设使用EJB2.0规范的Local接口代替Remote接口。

5.用"transient"关键字声明不必要的数据变量,替代以前的"public"、"private"等,避免不必要的数据变量占用网络资源。示例:

public class DemoCMP implements EntityBean {
transient EntityContext entCtx;
transient InitialContext initCtx;
public String id;
public String description;

}

6.在ejb-jar.xml部署文件中,对Session Bean中非事务的方法,将trans-attribute属性赋为"NotSupported"或"Never"






abookesessionBean
*

NotSupported




7. 设置事务的超时时间,在JBoss中,要修改${jboss.home}/server/${jboss.configuration}/conf/jboss-service.xml ,如下所示:



name="jboss:service=TransactionManager">
300




8.当事务锁定数据库的行记录时,事务应跨越可能的最小的时间。

9.调整EJB 服务器的各种参数,如线程数、EJB池大小、连接池参数等。以在JBoss修改连接池参数为示例,进行说明。如果JBoss和Mysql相连,配置${jboss.home}/server/${jboss.configuration}/deploy/mysql-service.xml,来修改连接池参数,包括MinSize、MaxSize、BlockingTimeoutMillis、IdleTimeoutMinutes、Criteria等,各参数的含义如下所示:

i.MinSize :连接池保持的最小连接数。

ii. MaxSize :连接池保持的最大连接数。

iii. BlockingTimeoutMillis :抛出异常前最大的等待连接时间。

iv. IdleTimeoutMinutes :关闭连接前连接空闲的最大时间。

v. Criteria :有ByContainerAndApplication、ByContainer、ByApplication和ByNothing等值。

下面是一个例子:



name="jboss.jca:service=LocalTxPool,name=MySqlDS">
0
50
5000
15
ByContainer



10.对于数据库事务,应选择较低成本的事务等级,避免造成坏数据。递增成本的事务等级包括:

TRANSACTION_READ_UNCOMMITED,
TRANSACTION_READ_COMMITED,
TRANSACTION_REPEATABLE_READ,
TRANSACTION_SERIALIZABLE

5楼2005-07-02 23:42:44
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 wswswws 的主题更新
普通表情 高级回复 (可上传附件)
信息提示
请填处理意见