软件构件与中间件技术 - EJB续
课程信息
课程大纲
- 会话构件
- 实体构件
- 消息驱动构件
EJB 构件分类
会话构件
- 有态会话构件: BMP (Bean-Managed Persistence)
- 无态会话构件: CMP (Container-Managed Persistence)
实体构件
- 特征:
- 持久性
- 可以同时为多个客户服务
- 生命周期较长
- 当 EJB 容器崩溃时,可以被恢复
消息驱动构件
- 特征:
- 为单个客户发出的消息服务
- 不直接表示数据库中的共享数据
- 生命周期相对较短
- 无状态
EJB 3.0
- 简化:
- 减少了在创建 EJB 时所需的类、接口、部署描述符的数量
- 使用纯旧式 Java 对象(POJO)和纯旧式 Java 接口(POJI)
实例代码
有状态会话 Bean 实例: HotelClerk bean
import javax.ejb.SessionBean;
import javax.naming.InitialContext;
public class HotelClerkBean implements SessionBean {
InitialContext jndiContext;
//conversational-state
Customer cust;
Vector resVector = new Vector();
public void ejbCreate(Customer customer) {
cust = customer;
}
public void addReservation(Name name, RoomInfo ri, Date from, Date to) {
ReservationInfo resInfo = new ReservationInfo(name, ri, from, to);
resVector.addElement(resInfo);
}
public void reserveRooms() {
CreditCard card = cust.getCreditCard();
Enumeration resEnum = resVector.elements();
while (resEnum.hasMoreElements()) {
ReservationInfo resInfo = (ReservationInfo) resEnum.nextElement();
RoomHome roomHome = (RoomHome) getHome("java:comp/env/ejb/RoomEJB", RoomHome.class);
Room room = roomHome.findByPrimaryKey(resInfo.roomInfo.getID());
double amount = room.getPrice(resInfo.from, resInfo.to);
CreditServiceHome creditHome = (CreditServiceHome) getHome("java:comp/env/ejb/CreditServiceEJB", CreditServiceHome.class);
CreditService creditAgent = creditHome.create();
creditAgent.verify(card, amount);
ReservationHome resHome = (ReservationHome) getHome("java:comp/env/ejb/ReservationEJB", ReservationHome.class);
Reservation reservation = resHome.create(resInfo.getName(), resInfo.roomInfo, resInfo.from, resInfo.to);
}
}
public RoomInfo[] availableRooms(Location loc, Date from, Date to) {
// Make an SQL call to find available rooms
}
private Object getHome(String path, Class type) {
Object ref = jndiContext.lookup(path);
return PortableRemoteObject.narrow(ref, type);
}
}
无状态会话 Bean 实例: CreditService bean
import javax.ejb.SessionBean;
public class CreditServiceBean implements SessionBean {
URL acmeURL;
HttpURLConnection acmeCon;
public void ejbCreate() {
try {
InitialContext jndiContext = new InitialContext();
acmeURL = (URL) jndiContext.lookup("java:comp/ejb/env/url/acme");
acmeCon = acmeURL.openConnection();
} catch (Exception e) {
throw new EJBException(e);
}
}
public void verify(CreditCard card, double amount) {
String response = post("verify:" + card.postString() + ":" + amount);
if (response.substring("approved") == -1)
throw new CreditServiceException("denied");
}
public void charge(CreditCard card, double amount) throws CreditServiceException {
String response = post("charge:" + card.postString() + ":" + amount);
if (response.substring("approved") == -1)
throw new CreditServiceException("denied");
}
private String post(String request) {
try {
acmeCon.connect();
acmeCon.setRequestMethod("POST " + request);
String response = acmeCon.getResponseMessage();
} catch (IOException ioe) {
throw new EJBException(ioe);
}
}
public void ejbRemove() {
acmeCon.disconnect();
}
public void setSessionContext(SessionContext cntx) {}
public void ejbActivate() {}
public void ejbPassivate() {}
}
EJB 3.0 实例
package com.foshanshop.ejb3;
public interface HelloWorld {
public String SayHello(String name);
}
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 + "说:你好!!";
}
}
实体 Bean 实例
import javax.ejb.EntityBean;
public class CustomerBean implements EntityBean {
int customerID;
Address myAddress;
Name myName;
CreditCard myCreditCard;
// CREATION METHODS
public Integer ejbCreate(Integer id) {
customerID = id.intValue();
return null;
}
public void ejbPostCreate(Integer id) {}
public Customer ejbCreate(Integer id, Name name) {
myName = name;
return ejbCreate(id);
}
public void ejbPostCreate(Integer id, Name name) {}
// BUSINESS METHODS
public Name getName() {
return myName;
}
public void setName(Name name) {
myName = name;
}
public Address getAddress() {
return myAddress;
}
public void setAddress(Address address) {
myAddress = address;
}
public CreditCard getCreditCard() {
return myCreditCard;
}
public void setCreditCard(CreditCard card) {
myCreditCard = card;
}
// CALLBACK METHODS
public void setEntityContext(EntityContext cntx) {}
public void unsetEntityContext() {}
public void ejbLoad() {}
public void ejbStore() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void ejbRemove() {}
}
Customer Bean 从属对象定义
// The Name class
public class Name implements Serializable {
public String lastName, firstName, middleName;
public Name(String lastName, String firstName, String middleName) {
this.lastName = lastName;
this.firstName = firstName;
this.middleName = middleName;
}
public Name() {}
}
// The Address class
public class Address implements Serializable {
public String street, city, state, zip;
public Address(String street, String city, String state, String zip) {
this.street = street;
this.city = city;
this.state = state;
this.zip = zip;
}
public Address() {}
}
// The CreditCard class
public class CreditCard implements Serializable {
public String number, type, name;
public Date expDate;
public CreditCard(String number, String type, String name, Date expDate) {
this.number = number;
this.type = type;
this.name = name;
this.expDate = expDate;
}
public CreditCard() {}
}
CustomerBean 到数据库表的映射
CREATE TABLE CUSTOMER {
id INTEGER PRIMARY KEY,
last_name CHAR(30),
first_name CHAR(20),
middle_name CHAR(20),
street CHAR(50),
city CHAR(20),
state CHAR(2),
zip CHAR(9),
credit_number CHAR(20),
credit_date DATE,
credit_name CHAR(20),
credit_type CHAR(10)
}
远程接口实例: Customer bean 的远程接口定义
import javax.ejb.EJBObject;
public interface Customer extends EJBObject {
public Name getName() throws RemoteException;
public void setName(Name name) throws RemoteException;
public Address getAddress() throws RemoteException;
public void setAddress(Address address) throws RemoteException;
public CreditCard getCreditCard() throws RemoteException;
public void setCreditCard(CreditCard card) throws RemoteException;
}
EJB 与 IIOP
- 互操作: 通过 IIOP 调用 home 接口与 remote 接口
- 事务传播: 通过 IIOP 传播事务上下文
- 安全传播: 通过 IIOP 传播安全上下文
- 命名空间: 通过 IIOP 组织命名空间
共性
- 基本形态相同
- 可以独立封装并可以动态加载
- 在运行过程中支持接口
- 都对构件进行生命周期管理
- 构件的运行环境包括众多的公共服务
区别
- 基础不同: EJB 规范吸收的是现有技术的解决方法,基本上不考虑对现有技术实现的兼容
- 支持环境的实现不同: EJB 的支持环境运行于操作系统之上,体现了一种大粒度的模块化思想
- 支持的语言不同: EJB 仅支持 Java 语言,COM 支持 C、C++、Basic 等
- 构件交互模式不同: 交互的协议、合约、标识方式皆不同
- 构件生命周期的实现方式不同: EJB 主要通过容器实现,独立于具体的构件实现;COM 主要通过类厂实现,与具体的构件实现一一对应
思考题
- EJB 构件包含哪些接口?
- EJB 构件是如何封装的?
- EJB 构件是如何分类的?
- COM 与 EJB 有什么异同?