b. 的解x(chng)?BR>
解决q个问题的方法是Q把客户端和他们使用的EJB分割开。徏议适用Session Fa?ade模式。这个模式通过一个Session BeanQؓ(f)一pd的EJB提供l一的接口来实现程。事实上Q当客户端只是用这个接口来触发程。这P所有关于EJB实现程所需要的改变Q都和客L(fng)无关?BR>
看下面这个例子。这D代码用来控制与客户相关的订单的处理Ҏ(gu)?BR>
// All imports required
// Exception handling not shown in the sample code
public class OrderSessionFacade implements SessionBean {
// all EJB specific methods like ejbCreate defined here
// Here is the business method that does the workflow
// required when a customer places a new order
public int placeOrder(String customerId, Details orderDetails)
throws RemoteException {
// Get reference to the required EJBs
InitialContext ctxt = new InitialContext();
Object obj = ctxt.lookup("java:comp/env/ejb/UserAccount");
UserAccountHome acctHome = (UserAccountHome)
PortableRemoteObject.narrow(obj, UserAccountHome.class);
UserAccount acct = acctHome.create();
obj = ctxt.lookup("java:comp/env/ejb/CreditCheck");
CreditCheckHome creditCheckHome = (CreditCheckHome)
PortableRemoteObject.narrow(obj, CreditCheckHome.class);
CreditCheck credit = creditCheckHome.create();
obj = ctxt.lookup("java:comp/env/ejb/Approvals");
ApprovalsHome apprHome = (ApprovalsHome)
PortableRemoteObject.narrow(obj, ApprovalsHome.class);
Approvals appr = apprHome.create();
obj = ctxt.lookup("java:comp/env/ejb/CommitOrder");
CommitOrderHome orderHome = (CommitOrderHome)
PortableRemoteObject.narrow(obj, CommitOrderHome.class);
CommitOrder order = orderHome.create();
// Now do the required workflow to place the order
int result = acct.checkStatus(customerId);
if(result != OK) {
// stop further steps
}
result = credit.checkCreditWorth(customerId, currentOrder);
if(result != OK) {
// stop further steps
}
result = appr.getApprovals(customerId, currentOrder);
if(result != OK) {
// stop further steps
}
// Everything OK; place the order
int orderId = order.placeOrder(customerId, currentOrder);
// Do other processing required
return(orderId);
}
// Implement other workflows for other order related functionalities (like
// updating an existing order, canceling an existing order etc.) in a
// similar way
}
在模式允许的情况下,Servlet代码很Ҏ(gu)实现?BR>
// all required imports
// exceptions to be caught appropriately wherever applicable
public class OrderHandlingServlet extends HttpServlet {
// all required declarations, definitions
public void init() {
// all inits required done here
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// other logic as required
// Get reference to the session facade
InitialContext ctxt = new InitialContext();
Object obj = ctxt.lookup("java:comp/env/ejb/OrderSessionFacade");
OrderSessionFacadeHome facadeHome = (OrderSessionFacadeHome)
PortableRemoteObject.narrow(obj, OrderSessionFacadeHome.class);
OrderSessionFacade facade = facadeHome.create();
// trigger the order workflow
int orderId = facade.placeOrder(customerId, currentOrder);
// do further processing as required
}
}
p上面昄的,客户端的逻辑变得非常单。流E中的Q何改变只要修Ҏ(gu)式中的一处地方就可以?jin)。客L(fng)可以仍旧使用原来的接口,而不必做M修改。同Pq个模式可以用来响应其他处理器的程处理。这让你能用同样的模式来处理不同客户端的不同程。在q个例子中,模式提供?jin)很好的伸羃性和可维护性?BR>c. 要点
既然q种模式不涉?qing)到数据讉KQ就应该用Session Bean来实现?BR>
对于用简单接口来实现复杂EJB的子pȝ来说Q是一个理想的选择?BR>
q个模式不适用于无程处理的应用?BR>
q个模式可以减少客户端于EJB之间的通信和依赖?BR>
所有和EJB有关的交互,都有同一个Session Bean来控Ӟ可以减少客户端对EJB的误用?BR>
q个模式可以使支持多cd客户端变得更Ҏ(gu)?BR>
可以减少|络数据传递?BR>
所有的服务器端的实现细节都对客L(fng)隐藏Q在改变发生后,客户端不用重新发布?BR>
q个模式可以同样看成一个集中处理器来处理所有的安全或日志纪录?BR>
4. Data Access Object
a. 问题
目前为止Q你看到的模型都是用来构建可伸羃的,易于l护的J2EE应用。这些模式尽可能的把应用在多个层上来实现。但是,q有一点必d调:(x)EJB的数据表现。它们包括象EJBq样的数据库语言。如果数据库有改变的话,相应的SQL也必L变,而EJB也必随之更新?BR>
q些常见问题是Q访问数据源的代码与EJBl合在一Pq样致代码很难l护。看以下的代码?BR>
An EJB that has SQL code embedded in it
// all imports required
// exceptions not handled in the sample code
public class UserAccountEJB implements EntityBean {
// All EJB methods like ejbCreate, ejbRemove go here
// Business methods start here
public UserDetails getUserDetails(String userId) {
// A simple query for this example
String query = "SELECT id, name, phone FROM userdetails WHERE name = " + userId;
InitialContext ic = new InitialContext();
datasource = (DataSource)ic.lookup("java:comp/env/jdbc/DataSource");
Connection dbConnection = datasource.getConnection();
Statement stmt = dbConnection.createStatement();
ResultSet result = stmt.executeQuery(queryStr);
// other processing like creation of UserDetails object
result.close();
stmt.close();
dbConnection.close();
return(details);
}
}
b. 的解x(chng)?BR>
Z(jin)解决q个问题Q从而让你能很方便的修改你的数据讉K。徏议用DAO模式。这个模式把数据讉K逻辑从EJB中拿出来攑օ独立的接口中。结果是EJB保留自己的业务逻辑Ҏ(gu)Q在需要数据的时候,通过DAO来访问数据库。这L(fng)模式Q在要求修改数据讉K的时候,只要更新DAO的对象就可以?jin)。看以下的代码?BR>
A Data Access Object that encapsulates all data resource access code
// All required imports
// Exception handling code not listed below for simplicity
public class UserAccountDAO {
private transient Connection dbConnection = null;
public UserAccountDAO() {}
public UserDetails getUserDetails(String userId) {
// A simple query for this example
String query = "SELECT id, name, phone FROM userdetails WHERE name = " + userId;
InitialContext ic = new InitialContext();
datasource = (DataSource)ic.lookup("java:comp/env/jdbc/DataSource");
Connection dbConnection = datasource.getConnection();
Statement stmt = dbConnection.createStatement();
ResultSet result = stmt.executeQuery(queryStr);
// other processing like creation of UserDetails object
result.close();
stmt.close();
dbConnection.close();
return(details);
}
// Other data access / modification methods pertaining to the UserAccountEJB
}
现在你有?jin)一个DAO对象Q利用这个对象你可以讉K数据。再看以下的代码?BR>
An EJB that uses a DAO
// all imports required
// exceptions not handled in the sample code
public class UserAccountEJB implements EntityBean {
// All EJB methods like ejbCreate, ejbRemove go here
// Business methods start here
public UserDetails getUserDetails(String userId) {
// other processing as required
UserAccountDAO dao = new UserAccountDAO();
UserDetails details = dao.getUserDetails(userId);
// other processing as required
return(details);
}
}
M数据源的修改只要更新DAO可以解决了(jin)。另外,Z(jin)支持应用能够支持多个不同的数据源cdQ你可以开发多个DAO来实玎ͼq在EJB的发布环境中指定q些数据源类型。在一般情况下QEJB可以通过一个Factory对象来得到DAO。用q种Ҏ(gu)实现的应用,可以很容易的改变它的数据源类型?BR>
c. 要点
q个模式分离?jin)业务逻辑和数据访问逻辑?BR>
q种模式特别适用于BMP。过一D|_(d)q种方式同样可以UL到CMP中?BR>
DAOs可以在发布的时候选择数据源类型?BR>
DAOs增强?jin)应用的可~性,因ؓ(f)数据源改变变得很Ҏ(gu)?BR>
DAOsҎ(gu)据访问没有Q何限Ӟ甚至可以讉KXML数据?BR>
使用q个模式导致增加一些额外的对象Qƈ在一定程度上增加应用的复杂性?BR>