J2ee应用程序设计――多层框架

发表于:2007-07-04来源:作者:点击数: 标签:
本人从事j2ee的设计已又多年,对j2ee框架,和其设计模式有较深,以下是我在 开发 过程中提出的一个框架,供大家参考,此框架使用以下设计模式:session faccedil;ade,general Attibute method,jdbc for reading,business delegate,home factory,data access
本人从事j2ee的设计已又多年,对j2ee框架,和其设计模式有较深,以下是我在开发过程中提出的一个框架,供大家参考,此框架使用以下设计模式:session fa&clearcase/" target="_blank" >ccedil;ade,general Attibute method,jdbc for reading,business delegate,home factory,data access command bean
综述
关于j2ee的框架设计的中心思想是:one transaction ,one invocation,,现今很多相应的设计思想和模式都是基于此。这个思想将贯穿于这个文章中,为了做到高性能,可复用性,可扩展性,将其框架分为五层:persistence 层,domain层,server 层,aplication 层,presentation 层,以下我将对各层做相应的阐述,并用wsad做一个实例,以供大家查考。
persistence 层
作用:用于访问底层资源,提供公共接口,例如javamail,jms等,以下以连接池为例
模型:data access command bean
建立一些用于与连接池打交道的class,将domain层与数据库隔离。
相应操作:(使用wsad)
打开java perspective,在ejbmodel目录下建立一个package,命名为com.aostar.persisitence

在相应的package里建立一个新的class,命名为DataBase.class,用于取得连接
编写代码如下:
package com.aostor.persistence;
import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;


public class Database
{
public static Connection getConnection()
throws Exception
{
Context ctx=null;
Try
{
ctx=new InitialContext();
DataSource dt=(DataSource)ctx.lookup("jdbc/template");
return dt.getConnection();
}
catch(Exception ex)
{
ex.printStackTrace();
throw new Exception("the class of Database error:"+ex.toString());
}
finally
{
if(ctx!=null)
{
try
{
ctx.close();
}
catch(Exception ex)
{
}
ctx=null;
}
}
}
}
然后做一个dacb,建立新class,DataAccessBean,采用的模型:proxy model,代码如下
package com.aostor.persistence;

import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;


public class DataAccessBean
{
/**
* variebles
*
*/
String sql="";
String jdbcName=Database.Oracle;
Connection con=null;
PreparedStatement pstt=null;
/**
* setSql
*
* @param value String
*/
public void setSql(String value)
throws NotConnectionException
{
try
{
if(con==null)
{
con=Database.getConnection(jdbcName);
}
sql=value;
pstt=con.prepareStatement(value,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
}
catch(Exception ex)
{
ex.printStackTrace();
throw new NotConnectionException(Database.Oracle+"can't be connection");
}
}
/**
* setSql
*
* @param value String
* @param resultSetType int
* @param resultSetCurrent int
*/
public void setSql(String value,int resultSetType,int resultSetCurrent)
throws NotConnectionException
{
try
{
if(con==null)
{
con=Database.getConnection(jdbcName);
}
sql=value;
pstt=con.prepareStatement(value,resultSetType,resultSetCurrent);
}
catch(Exception ex)
{
ex.printStackTrace();
throw new NotConnectionException(Database.Oracle+"can't be connection");
}
}
/**
* close
*
*/
public void close()
throws NotCloseException
{
if(pstt!=null)
{
try
{
pstt.close();
}
catch(Exception ex)
{
ex.printStackTrace();
throw new NotCloseException(ex.toString());
}
pstt=null;
}
if(con!=null)
{
try
{
con.close();
}
catch(Exception ex)
{
ex.printStackTrace();
throw new NotCloseException(ex.toString());
}
con=null;
}
sql="";
}
/**
* setJdbcName
* @param jdbcName String
*/
public void setJdbcName(String jdbcName)
{
if(con!=null)
{
try
{
close();
}
catch(NotCloseException ex)
{
}
}
this.jdbcName=jdbcName;
}
/**
* setString
* @param value String
* @param col,int
*/
public void setString(int col,String value)
{
try
{
pstt.setString(col,value);
}catch(SQLException ex){
}
}
/**
* setInt
* @param value int
* @param col int
*/
public void setInt(int col,int value){
try{
pstt.setInt(col,value);
}catch(SQLException ex){
}
}
/**
* setFloat
* @param value Float
* @param col int
*/
public void setFloat(int col,float value){
try{
pstt.setFloat(col,value);
}catch(SQLException ex){
}
}
/**
* setDouble
* @param value Double
* @param col int
*/
public void setDouble(int col,double value){

try{
pstt.setDouble(col,value);
}catch(SQLException ex){
}
}
/**
* setLong
* @param value long
* @param col int
*/
public void setLong(int col,long value){
try{
pstt.setLong(col,value);
}catch(SQLException ex){
}
}
/**
* setByte
* @param value byte
* @param col int
*/
public void setByte(int col,byte value){
try{
pstt.setByte(col,value);
}catch(SQLException ex){
}
}
/**
* setBytes
* @param value byte[]
* @param col int
*/
public void setBytes(int col,byte[] value){
try{
pstt.setBytes(col,value);
}catch(SQLException ex){
}
}
/**
* setShort
* @param value Short
* @param col int
*/
public void setShort(int col,short value){
try{
pstt.setShort(col,value);
}catch(SQLException ex){
}
}
/**
* setBigDecimal
* @param value BigDecimal
* @param col int
*/
public void setBigDecimal(int col,BigDecimal value){
try{
pstt.setBigDecimal(col,value);
}catch(SQLException ex){
}
}
/**
* setBoolean
* @param value boolean
* @param col int
*/
public void setBoolean(int col,boolean value){
try{
pstt.setBoolean(col,value);
}catch(SQLException ex){
}
}
/**
* setDate
* @param value Date
* @param col int
*/
public void setDate(int col,Date value){
try{
pstt.setDate(col,value);
}catch(SQLException ex){
}
}
/**
* setTime
* @param value Time
* @param col int
*/
public void setTime(int col,Time value){
try{
pstt.setTime(col,value);
}catch(SQLException ex){
}
}
/**
* setTimestamp
* @param value Timestamp
* @param col int
*/
public void setTimestamp(int col,Timestamp value){
try{
pstt.setTimestamp(col,value);
}catch(SQLException ex){
}
}
/**
* setClob
* @param value Clob
* @param col int
*/
public void setClob(int col,Clob value){
try{
pstt.setClob(col,value);
}catch(SQLException ex){
}
}
/**
* setBlob
* @param value Blob
* @param col int
*/
public void setBlob(int col,Blob value){
try{
pstt.setBlob(col,value);
}catch(SQLException ex){
}
}
/**
* setObject
* @param value int
* @param col int
*/
public void setObject(int col,Object value){
try{
pstt.setObject(col,value);
}catch(SQLException ex){
}
}
/**
* setArray
* @param value Array
* @param col int
*/
public void setArray(int col,Array value){
try{
pstt.setArray(col,value);
}catch(SQLException ex){
}
}
/**
* setNull
* @param value int
* @param col int
*/
public void setNull(int col,int value){
try{
pstt.setNull(col,value);
}catch(SQLException ex){

}
}
/**
* getMetaData
* @return MetaData
*/
public ResultSetMetaData getMetaData()
throws SQLException{

try{
return pstt.getMetaData();
}catch(SQLException ex){
throw ex;
}
}
/**
* execute
*/
public boolean execute()
throws SQLException{
try{
doLog();
return pstt.execute();
}catch(SQLException ex){
doError();
ex.printStackTrace();
throw ex;
}

}
/**
* executeQuery
*/
public ResultSet executeQuery()
throws SQLException{
try{
doLog();
return pstt.executeQuery();
}catch(SQLException ex){
doError();
ex.printStackTrace();
throw ex;
}
}

/**
* executeUpdate
*/
public int executeUpdate()
throws SQLException{
try{
doLog();
return pstt.executeUpdate();
}catch(SQLException ex){
doError();
ex.printStackTrace();
throw ex;
}
}
/**
* doLog
*/
void doLog(){
}
/**
* doError()
*/
void doError(){
}

}
两个异常:
package com.aostor.persistence;
public class NotCloseException extends Exception {

/**
* Constructor for NotCloseException
*/
public NotCloseException() {
super();
}

/**
* Constructor for NotCloseException
*/
public NotCloseException(String arg0) {
super(arg0);
}

}

package com.aostor.persistence;
public class NotConnectionException extends Exception {

/**
* Constructor for NotConnectionException
*/
public NotConnectionException() {
super();
}

/**
* Constructor for NotConnectionException
*/
public NotConnectionException(String arg0) {
super(arg0);
}

}


在sever perspective中建立连接池
打开服务器配置文件,sever-cfg.xml
选定视图界面中Data source
以下以oralce为例
先建立jdbc driver
Name:OracleIdbcDriver
Description:Oracle9i JDBC Driver
前两项为名称和描述,可随意配置
Implementation class name oracle.jdbc.pool.OracleConnectionPoolDataSource
URL prefix:jdbc:oracle:thin
Class:c:/oracle/ora92/jdbc/lib/classes12.zip
然后建立Data Source
Name:Session Persistence Datasource
JNDI name:jdbc/template
Database name:ao8226
Default user id:feinst
Default user user password:*
其他缺省,或为空
最后建立resource property
name:URL (大写)
Type:java.lang.String
Value:jdbc:oracle:thi:@ao-8226(服务器名称):1521:ao8226(数据库名)
Description :
说明:此层可由专人写出,打包,以后,由各位导入既可,但连接池必须自己配置,可方便大家做模块测试之用.
Database JDBC Driver
Oracle 8i Oracle Thin Driver Version 8.1.6.0.1Merant DataDirect Oracle Driver 2.2
Oracle 9i Oracle Thin Driver Version 8.1.7
Microsoft SQL Server 7.0 Merant DataDirect SQL Server Driver 2.2JTurbo SQL Server Driver 2.0i-Net Sprinta 4.15 SQL Server Driver
MySQL Max 3.23.48 mm.mysql 2.0.4
Informix 7.3.0 TC3 Informix JDBC Driver for Informix Dynamic Server 2.10.JC1N361Merant DataDirect Informix Driver 2.2
Cloudscape 4.0 Cloudscape 4.0 JDBC Driver 4.0Cloudscape 4.0 RMI JDBC Driver 4.0
MySQL 3.28 with InnoDB tables MySQL 2.0.4 driver
Sybase 12.5 jConnect for JDBC 5.5
以上为其他数据的jdbc引擎,配置基本相同
domain层
此层主要是用一些bmp或cmp封装usercase的buisness thing,至于选用何种bean,视情况而定,
一般来说,当数据库的table已存在,大多用bmp,
bmp
其命名规则如下:
com.模块名称.domain.bean名称
进入j2ee perspective,
建立一个新的enterprise bean

编写代码:
考虑到ejb server和container的版本不同,如果是ejb1.x,只写一套接口,如EJBHome和EJBObject的接口,如果是ejb2.0,需写两套接口,EJBHome,EJBObject,和EJBLocalHome,
EJBLocalObject接口,两者没有多大的区别,只是前者要抛出RemoteException异常,需要指出的是接口的中的方法不需要自己写,因为可以在其对应的bean中,用工具成生。Bean中method名称前有ejb的为容器调用方法,
代码编写原则是如果method中的放回值和参数,能够用接口的,必须用接口,已方便以后的扩展
如图:(生成Home接口和远端接口)


a、 TdomainHome(Home接口)
import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.FinderException;

/**
* Home interface for Enterprise Bean: TDomain
*/
public interface TDomainHome extends javax.ejb.EJBHome
{
/**
* Creates an instance from a key for Entity Bean: TDomain
*/
public TDomain create() throws javax.ejb.CreateException, java.rmi.RemoteException;
/**
* Finds an instance using a key for Entity Bean: TDomain
*/
public TDomain findByPrimaryKey(TDomainKey primaryKey) throws javax.ejb.FinderException, java.rmi.RemoteException;
/**
* ejbCreate
* @param id String
* @param name String
* @param birth String
* @param sex char
* @return TDomainKey
*/
public TDomain create(String id,String name,String birth,char sex)
throws CreateException, java.rmi.RemoteException;
}
b、 Tdomain(远端接口)
import java.rmi.RemoteException;
import java.util.HashMap;

import javax.ejb.EJBObject;

/**
* Remote interface for Enterprise Bean: TDomain
*/
public interface TDomain extends javax.ejb.EJBObject
{

/**
* generic Attribute method
* @param Attri hashMap
*
*/
public void changeValue(HashMap attri) throws java.rmi.RemoteException;
}

c、TDomainBean
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;

import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.ejb.RemoveException;

import com.aostor.persistence.Database;

/**
* Bean implementation class for Enterprise Bean: TDomain
*/
public class TDomainBean implements javax.ejb.EntityBean
{
private javax.ejb.EntityContext myEntityCtx;
/**
* getEntityContext
*/
public javax.ejb.EntityContext getEntityContext()
{
return myEntityCtx;
}
/**
* setEntityContext
*/
public void setEntityContext(javax.ejb.EntityContext ctx)
{
myEntityCtx = ctx;
}
/**
* unsetEntityContext
*/
public void unsetEntityContext()
{
myEntityCtx = null;
}
/**
l ejbActivate
l 容器管理bean时,当bean进入活跃时,应做的一些操作
*/
public void ejbActivate()
{
//id在table中对应pk
id=((TDomainKey)myEntityCtx.getPrimaryKey()).getValue();
}
/**
* ejbCreate
*/
public TDomainKey ejbCreate() throws javax.ejb.CreateException
{
return null;
}
/**
l ejbFindByPrimaryKey与home接口的findByPriamryKey对应
l 用主键查找bean
*/
public TDomainKey ejbFindByPrimaryKey(TDomainKey primaryKey) throws javax.ejb.FinderException
{
DataAccessBean dab=new DataAccessBean();
Try
{

//connection
dab.setSql("select * from template1 where id =? ");
dab.setString(1,primaryKey.getValue());
//execute:insert into template (id) values ?
ResultSet rs=dab.executeQuery();
rs.next();
id=rs.getString("id");
return primaryKey;

}
catch(Exception ex)
{


throw new FinderException("the class of TDomain :"+ex.toString());
}
finally
{
if(dab!=null)
{
try
{
dab.close();
}
catch(Exception ex)
{
}
dab=null;
}
}
}
/**
l ejbLoad
l bean活跃时应装入的数据项
*/
public void ejbLoad()
{
DataAccessBean dab=new DataAccessBean();

Try
{
//connection
dab.setSql("select * from template1 where id =?");
dab.setString(1,id);
//execute:insert into template (id) values ?
ResultSet rs=dab.executeQuery();
if(rs.next())
{
this.name=rs.getString("name");
this.birth=rs.getString("birth");
this.sex=rs.getString("sex").charAt(0);
}
else
{
throw new EJBException("this bean don't exist :id:"+id);
}


}
catch(Exception ex)
{
ex.printStackTrace();


}
finally
{
if(dab!=null)
{
try
{
dab.close();
}
catch(Exception ex)
{
}
dab=null;
}
}
}
/**
l ejbPassivate
l bean处于非活跃状态时,应做的操作
*/
public void ejbPassivate()
{
id=null;
}
/**
* ejbPostCreate
*/
public void ejbPostCreate() throws javax.ejb.CreateException
{
}
/**
l ejbRemove
l 删除bean,永久删除,不常用
*/
public void ejbRemove() throws javax.ejb.RemoveException
{
DataAccessBean dab=new DataAccessBean();

Try
{
//connection
dab.set("delete from template1 where id =? ");
dab.setString(1,id);
//execute:insert into template (id) values ?
dab.executeUpdate();


}
catch(Exception ex)
{
ex.printStackTrace();
throw new RemoveException("the class of TDomain:"+ex.toString());


}
finally
{
if(dab!=null)
{
try
{
dab.close();
}
catch(Exception ex){
}
dab=null;
}
}
}
/**
l ejbStore
l bean处于非活跃状态时,应将数据项中的指装入数据库或其他可持续的地方
*/
public void ejbStore()
{
DataAccessBean dab=new DataAccessBean();

If(isModified){
Try
{
//connection
dab.setSql("update template1 set name =?,birth =?,sex =? where id =? ");
dab.setString(1,name);
dab.setString(2,birth);
dab.setString(3,String.valueOf(sex));
dab.setString(4,id);
//execute:insert into template (id) values ?
dab.executeUpdate();
isModified=false;


}
catch(Exception ex)
{
ex.printStackTrace();

}
finally
{
if(dab!=null)
{
try
{
dab.close();
}
catch(Exception ex)
{
}
dab=null;
}
}
}
}
/**
l domains
l 数据项,尽量设立缺省值
*/
String name="guest";
String id;
String birth="20000000";
char sex='f';
boolean isModified=false;
/**
l ejbPostCreate
l 与ejbCreate同时存在,,用于创建,
l ejbCreate用于创建新项,ejbPostCreate用与创建后应做的事,有先后顺序
l 与Home接口的Create方法对应,
l 注意三者的异常和返回值,一般来说,ejbCreate返回其主键类,Create返回其远端接口,两者除了Create的RemoteException异常外,必须用于相同的异常,其次CreateException必须有
l ejbPostCreate一般没有返回值,没有异常
l 由于container的调用顺序为ejbCreate,ejbPostCreate,Store,所以在生成新项时先要对每一个没有缺省值的数据项设值,特别时主键,要注意此点,否则会出现无法想象的结果
* @param id String
* @param name String
* @param birth String
* @param sex char
*/
public void ejbPostCreate(String id,String name,String birth,char sex)
{
}
/**
* ejbCreate
* @param id String
* @param name String
* @param birth String
* @param sex char
* @return TDomainKey
*/
public TDomainKey ejbCreate(String id,String name,String birth,char sex)
throws CreateException
{
DataAccessBean dab=new DataAccessBean();

Try
{
//set values
this.id=id;
this.name=name;
this.birth=birth;
this.sex=sex;
//connection
dab.setSql("insert into template1 (id) values (?) ");
dab.setString(1,id);
//execute:insert into template (id) values ?
dab.executeUpdate();
return new TDomainKey(id);

}
catch(Exception ex)
{
ex.printStackTrace();
throw new CreateException("the class of TDomain :"+ex.toString());
}
finally
{
if(dab!=null)
{
try
{
dab.close();
}
catch(Exception ex)
{
}
dab=null;
}
}

}

/**
* Gets the name
* @return Returns a String
*/
public String getName()
{

return name;
}
/**
* Sets the name
* @param name The name to set
*/
public void setName(String name)
{
if(this.name.equals(name))isModified=true;
this.name = name;
}

/**
* Gets the birth
* @return Returns a String
*/
public String getBirth()
{
return birth;
}
/**
* Sets the birth
* @param birth The birth to set
*/
public void setBirth(String birth)
{
if(this.birth.equals(birth))isModified=true;
this.birth = birth;
}

/**
* Gets the sex
* @return Returns a char
*/
public char getSex()
{
return sex;
}
/**
* Sets the sex
* @param sex The sex to set
*/
public void setSex(char sex)
{
if(this.sex.equals(sex))isModified=true;
this.sex = sex;
}
/**
l generic Attribute method
l 此处用于修改数据,采用了generic Attribute method 模式,主要是为了减少远端调用并提供了通用的调用方式,
* @param Attri hashMap
*
*/
public void changeValue(HashMap attri)
{

if(attri.containsKey("name"))
{
setName((String)attri.get("name"));
}
if(attri.containsKey("sex"))
{
setSex(((String)attri.get("sex")).charAt(0));
}
if(attri.containsKey("birth"))
{
setBirth((String)attri.get("birth"));
}

}

}
d、TdomainKey
在java perspective中,修改TdomainKey
将主键加入到代码中
/**
* Key class for Entity Bean: TDomain
*/
public class TDomainKey implements java.io.Serializable
{
static final long serialVersionUID = 3206093459760846163L;
/**
* primary key
*/
String id;
/**
* Creates an empty key for Entity Bean: TDomain
*/
public TDomainKey()
{
}
/**
* Creates an empty key for Entity Bean: TDomain
*/
public TDomainKey(String id)
{
this.id=id;
}
/**
* Returns true if both keys are equal.
*/
public boolean equals(java.lang.Object otherKey)
{
if (otherKey instanceof TDomainKey)
{
TDomainKey o = (TDomainKey)otherKey;
return (id.equals(o.getValue()));
}
return false;
}
/**
* Return value of primarykey
*/
public String getValue()
{
return id;
}
/**
* Returns the hash code for the key.
*/
public int hashCode()
{
return (id.hashCode());
}
}

部署代码,到j2ee perspective,在ejb项目中,如图操作

部署完成后既可运行发布,并调试代码,需注意的是,服务器可用两种方式启动,一种是正常方式,一种是调试方式(可单步跟踪)
调试需注意:分三步:每个ejb的模块调试,集成调试,系统调试(由专人负责)
模块调试的环境为:客户端测试环境,如图
其调用方法和程序调用相同
绑定name:其步骤,打开ejb extension editor,其绑定的名称为
name:ejb/Tdomain
见图


cmp
首先生成一个enterprise bean,bean type定为cmp,然后加入数据项(需要录入数据库的数据项)
如图:(注意必须设置主键)

输入代码:
a、 TdepartmentHome
import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.FinderException;

/**
* Home interface for Enterprise Bean: TDepartment
*/
public interface TDepartmentHome extends javax.ejb.EJBHome
{
/**
* Creates an instance from a key for Entity Bean: TDepartment
*/
public TDepartment create(java.lang.String id) throws javax.ejb.CreateException, java.rmi.RemoteException;
/**
* Finds an instance using a key for Entity Bean: TDepartment
*/
public TDepartment findByPrimaryKey(TDepartmentKey primaryKey) throws javax.ejb.FinderException, java.rmi.RemoteException;
/**
l Finds an instance using name for Entity Bean: TDepartment
l 注意在设计cmp时,对于finder方法,必须在home写出,然后在ejb 的扩展editor编写其sql语句,而不象bmp需要在bean class中写对应bean 方法,这一点需要注意
*/
public Collection findByName(String name) throws javax.ejb.FinderException, java.rmi.RemoteException;

/**
* ejbCreate
* @param id String
* @param name String
* @param director String
* @return TDepartmentKey
*/
public TDepartment create(String id,String name,String director)
throws CreateException, java.rmi.RemoteException;
}

b、 TDepartmentBean
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.ejb.RemoveException;

import com.ibm.ivj.ejb.associations.interfaces.Link;

/**
* Bean implementation class for Enterprise Bean: TDepartment
*/
public class TDepartmentBean implements javax.ejb.EntityBean {
private javax.ejb.EntityContext myEntityCtx;
/**
* Implemetation field for persistent attribute: id
*/
public java.lang.String id;
/**
* Implemetation field for persistent attribute: name
*/
public java.lang.String name;
/**
* Implemetation field for persistent attribute: director
*/
public java.lang.String director;
/**
* getEntityContext
*/
public javax.ejb.EntityContext getEntityContext()
{
return myEntityCtx;
}
/**
* setEntityContext
*/
public void setEntityContext(javax.ejb.EntityContext ctx)
{
myEntityCtx = ctx;
}
/**
* unsetEntityContext
*/
public void unsetEntityContext()
{
myEntityCtx = null;
}
/**
* ejbActivate
*/
public void ejbActivate()
{
_initLinks();
}
/**
* ejbCreate method for a CMP entity bean.
*/
public TDepartmentKey ejbCreate(java.lang.String id)
throws javax.ejb.CreateException
{
_initLinks();
this.id = id;
return null;
}
/**
* ejbLoad
*/
public void ejbLoad()
{
_initLinks();
}
/**
* ejbPassivate
*/
public void ejbPassivate()
{
}
/**
* ejbPostCreate
*/
public void ejbPostCreate(java.lang.String id) throws javax.ejb.CreateException
{
}
/**
* ejbRemove
*/
public void ejbRemove() throws javax.ejb.RemoveException
{
try
{
_removeLinks();
}
catch (java.rmi.RemoteException e)
{
throw new javax.ejb.RemoveException(e.getMessage());
}
}
/**
* ejbStore
*/
public void ejbStore()
{
}
/**
* This method was generated for supporting the associations.
*/
protected void _initLinks()
{
}
/**
* This method was generated for supporting the associations.
*/
protected java.util.Vector _getLinks()
{
java.util.Vector links = new java.util.Vector();
return links;
}
/**
* This method was generated for supporting the associations.
*/
protected void _removeLinks() throws java.rmi.RemoteException, javax.ejb.RemoveException
{
java.util.List links = _getLinks();
for (int i = 0; i < links.size() ; i++) {
try {
((com.ibm.ivj.ejb.associations.interfaces.Link) links.get(i)).remove();
} catch (javax.ejb.FinderException e) {} //Consume Finder error since I am going away
}
}
/**
* Get accessor for persistent attribute: name
*/
public java.lang.String getName()
{
return name;
}
/**
* Set accessor for persistent attribute: name
*/
public void setName(java.lang.String newName)
{
name = newName;
}
/**
* Get accessor for persistent attribute: director
*/
public java.lang.String getDirector()
{
return director;
}
/**
* Set accessor for persistent attribute: director
*/
public void setDirector(java.lang.String newDirector)
{
director = newDirector;
}
/**
* ejbCreate
* @param id String
* @param name String
* @param director String
* @return TDepartmentKey
*/
public TDepartmentKey ejbCreate(String id,String name,String director)
throws CreateException
{
this.id=id;
setName(name);
setDirector(director);
return null;
}
/**
* ejbPostCreate
* @param id String
* @param name String
* @param director String
* @return TDepartmentKey
*/
public void ejbPostCreate(String id,String name,String director)
{
}
/**
* generic Attribute method
* @param Attri hashMap
*
*/
public void changeValue(HashMap attri)
{

if(attri.containsKey("name"))
{
setName((String)attri.get("name"));
}
if(attri.containsKey("director"))
{
setDirector((String)attri.get("director"));
}

}
}

c、 TDepartment
import java.rmi.RemoteException;
import java.util.HashMap;

import javax.ejb.EJBObject;

/**
* Remote interface for Enterprise Bean: TDepartment
*/
public interface TDepartment extends javax.ejb.EJBObject
{
/**
* generic Attribute method
* @param Attri hashMap
*
*/
public void changeValue(HashMap attri) throws java.rmi.RemoteException;
}

ejb/rdb mapping(既是将数据项映射到映射数据库上),

生成map以后,可以查阅如下图

在ejb editor中,finder中,填写sql语句,一般来说可以选取Full select,或 whereclause,两者可用标准的sql表示,对于ejbql来说,适合ejb2.0



server层
用sessionbean封装usercase,每个method就是一个usercase
注意sessionbean中的所有方法,应只属于一个角色
进入j2ee perspective,过程与建立bmp一样,建立一个sessionbean
package的命名如下:
com.aostar.模块名称.server
其代码如下:
1、 TserverHome
/**
* Home interface for Enterprise Bean: Tserver
*/
public interface TserverHome extends javax.ejb.EJBHome
{
/**
* Creates a default instance of Session Bean: Tserver
*/
public Tserver create() throws javax.ejb.CreateException, java.rmi.RemoteException;
}

2、 Tserver
import java.rmi.RemoteException;

import javax.ejb.EJBObject;
import javax.sql.RowSet;

/**
* Remote interface for Enterprise Bean: Tserver
*/
public interface Tserver extends javax.ejb.EJBObject
{
/**
*
* jdbc for reading
* readData
* @param birth1 String
* @param birth2 String
*/
public RowSet readData(String birth1,String birth2) throws java.rmi.RemoteException;
/**
*
* create
* @param id String
* @param name String
* @param birth String
* @param sex char
*/
public void create(String id,String name ,String birth,String sex)
throws Exception, java.rmi.RemoteException;
}

3、 TserverBean
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;

import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.RowSet;
import sun.jdbc.rowset.CachedRowSet;

import com.aostor.persistence.Database;




/**
* Bean implementation class for Enterprise Bean: Tserver
*/
public class TserverBean implements javax.ejb.SessionBean
{
private javax.ejb.SessionContext mySessionCtx;
/**
* getSessionContext
*/
public javax.ejb.SessionContext getSessionContext()
{
return mySessionCtx;
}
/**
* setSessionContext
*/
public void setSessionContext(javax.ejb.SessionContext ctx)
{
mySessionCtx = ctx;
}
/**
* ejbActivate
*/
public void ejbActivate()
{
}
/**
* ejbCreate
*/
public void ejbCreate() throws javax.ejb.CreateException
{
}
/**
* ejbPassivate
*/
public void ejbPassivate()
{
}
/**
* ejbRemove
*/
public void ejbRemove()
{
}
/**
l getTDomainHome()
l 取得domain层的home接口
*/
public TDomainHome getTDomainHome()
throws Exception
{
Context cxt=null;
Try
{
cxt=new InitialContext();
return (TDomainHome)cxt.lookup("ejb/TDomain");
}catch(Exception ex)
{
ex.printStackTrace();
throw new Exception("the class of Tserver :"+ex.toString());

}
finally
{
if(cxt!=null)
{
try
{
cxt.close();
}
catch(Exception ex)
{
}
cxt=null;
}
}
}

/**
* 封装了Tdomain的修改和创建
* create
* @param id String
* @param name String
* @param birth String
* @param sex char
*/
public void create(String id,String name ,String birth,String sex)
throws Exception
{
TDomainHome home=null;
Try
{
//update,数据传输采用了HashMap模式
home=getTDomainHome();
TDomain domain=home.findByPrimaryKey(new TDomainKey(id));
HashMap attri=new HashMap();
attri.put("name",name);
attri.put("birth",birth);
attri.put("sex",sex);
domain.changeValue(attri);
}catch(FinderException fex)
{
//create
try
{
home.create(id,name,birth,sex.charAt(0));
}
catch(Exception ex)
{
ex.printStackTrace();
throw new Exception("the class of Tserver:"+ex.toString());
}

}catch(Exception ex)
{
ex.printStackTrace();
throw new Exception("the class of Tserver:"+ex.toString());

}
}
/**
l 查看多项数据
l 这里采用了jdbc for reading模式,数据传输采用了Rowset模式
* jdbc for reading
* readData
* @param birth1 String
* @param birth2 String
*/
public RowSet readData(String birth1,String birth2)
{
Connection con=null;
PreparedStatement pstt=null;
Try
{
//connection
con=Database.getConnection();
pstt=con.prepareStatement("select * from template1 where birth>=? and birth<=? ");
pstt.setString(1,birth1);
pstt.setString(2,birth2);
CachedRowSet rs=new CachedRowSet();
rs.populate(pstt.executeQuery());
rs.setTableName("template1");
return rs;
}
catch(Exception ex)
{
ex.printStackTrace();
return null;
}
finally
{
if(pstt!=null)
{
try
{
pstt.close();
}
catch(Exception ex)
{
}
pstt=null;
}
if(con!=null)
{
try
{
con.close();
}
catch(Exception ex)
{
}
con=null;
}
}
}
/**
*
* jdbc for reading
* readData
* @param birth1 String
* @param birth2 String
*/
public RowSet readDatatest(String birth1,String birth2)
{
DataAccessBean dab=new DataAccessBean();
Try
{
dab.setSql("select * from template1 where birth>=? and birth<=? ");
dab.setString(1,birth1);
dab.setString(2,birth2);
CachedRowSet rs=new CachedRowSet();
rs.populate(dab.executeQuery());
rs.setTableName("template1");
return rs;
}
catch(Exception ex)
{
ex.printStackTrace();
return null;
}
finally
{
if(dab!=null)
{
try
{
dab.close();
}
catch(Exception ex)
{
}
dab=null;
}
}
}



}
注意:由于远端调用,要穿越防火墙,所以数据传输非常重要,可能会影响了整个系统性能,一般采用以下几个模式:
hashmap模式:用HashMap来传递,见上面代码
DTO对象:DTO为数据传输对象,是序列化的,可在层与层之间的远端调用中传递,一般用于多行数据传递,可用于页面控制,需自己按需编写。
RowSet:多项数据传输,见上面代码
XML:多项数据传输,可用于页面控制
部署如domain层,调试如domain层
application 层]
作用:隔离ejb与jsp或者客户端程序,提供参数检验功能
businessdelegate
隔离表现层和server层,提供与server相同的方法,可增加数据类型检测了,一些论证
此处使用的时businessdelegate模型,一种在j2ee设计中最常用的模式,类似于模式设计中proxy模式
在java perspective中建立一个package,在其web项目的source目录下
com.aostar.模块名称.businessdelegate
建立一个class,Tbusiness
代码如下:
package com.aostar.delegate;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.RowSet;
import Tserver;
import TserverHome;


public class Tbuseness
{
/**
l getTDomainHome()
l 得到远端
l 如果存在大量的访问时,需要做一个专门的HomeFactory,用于控制和管理各个sessionBean的Home接口,并且它统一管理Home接口,并将businessdelegate和jininame隔离,因为jininame本身变动较大,这样HomeFactory很大程度的减少了代码修改,增加了代码的可复用性,代码如下
*/
public Tserver getTserver()
throws Exception
{
try
{
HomeFactory factory=HomeFactory.builder();

TserverHome home=(TserverHome)factory.findBy(TserverHome.class);
return home.create();
}
catch(Exception ex)
{
ex.printStackTrace();
throw ex;

}
}
/**
* update and create
* @param id String
* @param name String
* @param birth String
* @param sex String
*/
public void updateAndCreate(String id,String name ,String birth,String sex)
throws Exception
{
//check data
if(sex.length()!=1 && birth.length()!=8)
{
throw new Exception("error data formation");
}
//execute
try
{
Tserver delegate=getTserver();
delegate.create(id,name,birth,sex);
}
catch(Exception ex)
{
ex.printStackTrace();
throw new Exception("System error");
}
}
/**
* showData
* @param birth1 String
* @param birth2 String
* @return RowSet
*/
public RowSet showData(String birth1,String birth2)
throws Exception
{
//check data
if(birth1.length()!=8 && birth2.length()!=8)
{
throw new Exception("error data formation");
}
//execute
RowSet re=null;
Try
{
Tserver delegate=getTserver();
if((re=delegate.readData(birth1,birth2))==null)
{
throw new Exception("returnvalue is null");
}
}
catch(Exception ex)
{
ex.printStackTrace();
throw new Exception("System error");
}
return re;
}
}
在编译之前,需要导入所需ejb的包(包括Home,远端接口类,和一些成生的客户端调用class,考虑到储存空间现今已不是问题,可整个的打包),如图
在web perspective中,左键,出现下拉以后,点击properties进入相应界面

当然还有一种方式,就是在java build path 中project加入ejb项目既可,这是常用方法

备注:在项目中需要加入其他外面的包,比如说其他厂商开发的,如例子中引用了sun公司的RowSet包,方法于前一种类似,需要加入变量,但如果是ejb项目加包还需要包存放在运行目录中com.ibm.etools.websphere.runtime
HomeFactory
用于大型的项目,采用了singleton model 和 flightweight model相应的原因如上述
代码如下:
package com.aostar.home;
import java.util.HashMap;
import java.util.List;
import java.util.Arrays;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import TserverHome;

import com.aostar.exception.HomeFactoryCreateException;
public class HomeFactory
{
//singleton model
static HomeFactory factory=null;
//flightweight model
static HashMap map=null;
final static String[] jdbcName={"ejb/Tserver"};
final static Class[] classes={TserverHome.class};
final static int COUNT=1;
/**
* constructor
*/
private HomeFactory()
throws HomeFactoryCreateException
{
map=new HashMap();
Context ctx=null;
Try
{
ctx=new InitialContext();
List jdbcList=Arrays.asList(jdbcName);
for(int i=0;i {
Object obj=ctx.lookup((String)jdbcList.get(i));
obj=PortableRemoteObject.narrow(obj,classes);
map.put(classes,obj);

}
}
catch(Exception ex)
{
ex.printStackTrace();
throw new HomeFactoryCreateException("home factory can't start");
}
finally
{
if(ctx!=null)
` {
try
{
ctx.close();
}
catch(Exception ex)
{
}
ctx=null;
}
}

}
/**
* builder
*/
static public HomeFactory builder()
throws Exception
{

if(factory==null)
{
//try 15 times
boolean flag=true;
int i=1;
while(flag && i<=15)
{
try
{
factory=new HomeFactory();
flag=false;
}
catch(HomeFactoryCreateException ex)
{
}
i++;
}
if(flag){
throw new Exception("System error");
}
}


return factory;
}
/**
*
*/
public Object findBy(Class ref)
throws Exception
{
if(map.containsKey(ref))
{
return map.get(ref);
}
else
{
throw new Exception("this home don't exist");
}
}



}


一些java servlet
presentation
在其web perspective中,web Application
jsp和一些css,xsl(用于xml)等
以下为例子jsp:


原文转自:http://www.ltesting.net