首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

8.4 创建EJB模块

有了上一节配置的数据源,就可以在工程中创建实现操作login数据库的实体Bean模块,并部署到服务器上,然后登录示例,就可以通过访问这个模块来实现对应的功能。

8.4.1  创建EJB工程

1.创建工程UserEJB

首先创建开发EJB的工程UserEJB,单击【File】|【New Project…】命令菜单,弹出新建工程对话框,输入工程名称和目录,工程创建配置如图8-32所示。

图8-32  创建工程UserEJB

2.配置服务器

然后要配置服务器为Weblogic 8.1,步骤如下。

(1)单击【Project】|【Project Properties…】命令菜单,在工程配置对话框中选择“Server”项,单击其中的【…】按钮配置服务器,如图8-33所示。

图8-33  配置服务器

(2)在服务器列表中选中Weblogic8.1服务器,选中“Enable Server”复选框,如图8-34所示。

 

图8-34  配置服务器

(3)切换到“Custom”项,在这里配置一系列的属性,如图8-35所示,其中用户名为服务器的用户名“kingbill”,密码为“2222222”。

图8-35  “Custom”项内容

(4)切换到“General”项,如图8-36所示,这时“1”处显示了访问服务器的账户,“2”处被自动设置为正确的配置。另外需要手工导入数据库驱动,具体配置如图8-37所示。

图8-36  “General”项

(5)单击【OK】按钮,这时服务器被选择成刚才配置的Weblogic 8.1,如图8-38所示。

    

         图8-37  服务器为Weblogic8.1                图8-38  “Database Drivers”项内容

3.配置企业级应用数据库驱动

接下来配置企业级应用数据库驱动,步骤如下。

(1)单击【Enterprise】|【Enterprise Setup…】命令菜单,在Enterprise Setup对话框中选择“Database Drivers”项,如图8-38所示。

(2)单击【Add…】按钮,出现选择lib包对话框,选中前面内容中创建的MySQL数据库驱动的lib包,如图8-39所示。

(3)单击【OK】按钮,在“Database Drivers”列表中就增加了一项mysql.config配置,如图8-40所示。

      

        图8-39  选择lib包                        图8-40  增加了mysql.config配置

(4)单击【OK】按钮完成配置,系统提示重启Jbuilder 2005才能使配置生效。

8.4.2  创建EJB模块

接下来就可以在该工程中创建EJB模块,步骤如下。

(1)单击【File】|【New…】命令菜单,弹出新建对象向导对话框,选择EJB项中的“EJB Modul”图标,如图8-41所示。

(2)单击【OK】按钮,选择创建一个新的模块,如图8-42所示。

   

             图8-41  新建对象向导                           图8-42  创建一个新的模块

(3)单击【Next】按钮,输入模块的名称“user”,选择EJB版本为EJB 2.0,如图8-43所示。

(4)单击【Finish】按钮,工程中就出现了一个名为“user”的EJB模块,如图8-44所示。

 

         图8-43  创建EJB模块user                      图8-44  EJB模块白板(面板)

8.4.3  创建实体Bean

1.创建实体Bean

接下来要在该模块中创建对应login数据库中user表的实体Bean(CMP),步骤如下。

(1)在“Structure”面板中右击“DataSources”图标,选择“Import Schema From Database”,如图8-45所示。

图8-45  Import Schema From Database

(2)在弹出的“Database Schema Provider”对话框中,输入数据库驱动类名和数据库URL,以及在前面建立的数据源的名称“UserDataSource”,如图8-46所示,注意上面的“All Schemas”复选框一定要选上,否则将看不到数据库中表的列表信息。

图8-46  Database Schema Provider

(3)完成配置后单击【OK】按钮,在工程的“Structure”面板中就出现了该数据源,展开后可以看到其中有一张表“user”,以及该表的3个字段,如图8-47所示。

(4)在表“user”的图标上右击,在弹出的菜单中选择“Create CMP 2.0 Entity Bean”,来创建对应的实体Bean,如图8-48所示。

 

图8-47  “Structure”面板出现数据源

图8-48  Create CMP 2.0 Entity Bean

(5)系统创建的实体Bean会以可视化的方式显示在模块的白板中,如图8-49所示。

(6)在实体Bean的名称“User”上单击,会弹出该对象的属性对话框,将其中的“Interfaces”一项修改为“Local/Remote”,如图8-50、图8-51所示。

(7)完成上述操作后,该工程下共有5个类(其实是5个接口),如图8-52所示。

(8)为该实体Bean添加一个按照username查找的方法。在实体Bean的名称“User”上右击,依次选择【Add】|【Finder】项,如图8-53所示。

(9)配置该方法,各项配置如图8-54所示。注意其中输入的查询语句是EJB QL标准的SQL语句“select object(u) from User as u where u.username=?1”,EJB QL语句是对SQL语句标准的一个标准实现,同一般的SQL语句有所区别。

   

               图8-49  实体Bean                               图8-50  “属性”对话框

    

        图8-51  修改为“Local/Remote”                    图8-52  工程下共有5个类

     

             图8-53  添加Finder方法                     图8-54  配置Finder方法

2.实体Bean中的5个接口

完成上述操作后,基本的实体Bean就建立好了。这里简单介绍一下其中生成的5个接口。

*     本地接口User:实现具体数据库访问逻辑的代理接口,具体数据库访问逻辑则委托给Bean类,再由容器实现,换句话说就是与开发者无关,其代码如下(大致了解即可)。

代码8.1  本地接口

package userejb;

import javax.ejb.EJBLocalObject;

public interface User

    extends EJBLocalObject {

  public Integer getUserId();

  public void setUsername(String username);

  public String getUsername();

  public void setPassword(String password);

  public String getPassword();

}

*     本地Home接口UserHome:是生产本地接口的工厂,由JNDI查找获得。代码如下。

代码8.2  本地Home接口

package userejb;

import javax.ejb.EJBLocalHome;

import javax.ejb.CreateException;

import javax.ejb.FinderException;

public interface UserHome

    extends EJBLocalHome {

  public User create(Integer userId) throws CreateException;

  public User findByPrimaryKey(Integer userId) throws FinderException;

  public User findByUserName(String username) throws FinderException;

}

*     远程接口UserRemote:对应本地接口User。区别在于本地接口用于本地访问,远程接口用于远程访问,代码如下。

代码8.3  远程接口

package userejb;

import javax.ejb.EJBObject;

import java.rmi.RemoteException;

public interface UserRemote

    extends EJBObject {

  public Integer getUserId() throws RemoteException;

  public void setUsername(String username) throws RemoteException;

  public String getUsername() throws RemoteException;

  public void setPassword(String password) throws RemoteException;

  public String getPassword() throws RemoteException;

}

*     远程Home接口UserRemoteHome:对应本地Home接口。之所以造成本地接口与远程接口的分离,是因为EJB原本是为分布式应用设计的,开始根本没有考虑本地访问的情况,因此在EJB1.1的规范中只有远程接口,后来因为性能和需求的关系,才在EJB2.0中增加了本地接口。具体的代码如下。

代码8.4  远程Home接口

package userejb;

import javax.ejb.EJBHome;

import javax.ejb.CreateException;

import java.rmi.RemoteException;

import javax.ejb.FinderException;

public interface UserRemoteHome

    extends EJBHome {

  public UserRemote create(Integer userId) throws CreateException,

      RemoteException;

  public UserRemote findByPrimaryKey(Integer userId) throws FinderException,

      RemoteException;

  public UserRemote findByUserName(String username) throws FinderException, RemoteException;

}

*     Bean类UserBean:注意是abstract class,容器是根据这个类去实现具体逻辑,代码如下。

代码8.5  Bean类

package userejb;

import javax.ejb.EntityBean;

import javax.ejb.EntityContext;

import javax.ejb.CreateException;

import javax.ejb.RemoveException;

public abstract class UserBean

    implements EntityBean {

  EntityContext entityContext;

  public Integer ejbCreate(Integer userId) throws CreateException {

    setUserId(userId);

    return null;

  }

  public void ejbPostCreate(Integer userId) throws CreateException {

  }

  public void ejbRemove() throws RemoveException {

  }

  public abstract void setUserId(Integer userId);

  public abstract Integer getUserId();

  public abstract void setUsername(String username);

  public abstract String getUsername();

  public abstract void setPassword(String password);

  public abstract String getPassword();

  public void ejbLoad() {

  }

  public void ejbStore() {

  }

  public void ejbActivate() {

  }

  public void ejbPassivate() {

  }

  public void unsetEntityContext() {

    this.entityContext = null;

  }

  public void setEntityContext(EntityContext entityContext) {

    this.entityContext = entityContext;

  }

}

其中,各个方法的作用和操作方法可以参考专门的EJB著作。这里要说明的是,虽然可以直接编码访问这些接口,但是其实有更简单的方法,就是JBuider2005提供的配置生成的Facade模块,下面就来实现这个Facade模块。

8.4.4  实现Facade模块

Facade(门面模式)是J2EE实践中常用于封装EJB访问的设计模式,作用类似于代理。实际上,JBuilder2005实现的Facade模块综合运用了各种设计模式,来实现简化操作的目的。Facade模块的另外一个重要作用是:将对EJB的细粒度的get/set操作封装在本地实现,从而大大减少远程调用的次数和提升操作的粒度尺寸。实现这个Facade模块的具体操作如下。

(1)在实体Bean的名称“User”上右击,在弹出的菜单中选择【Launch DTO/Facade  Wizard】命令,如图8-55所示。

(2)弹出Facade配置向导,如图8-56所示,虽然该向导一共有7步,但是一般的应用并不需要修改其中的任何内容,因此这里直接跳过,有兴趣的读者可以仔细查看其详细配置,前提是对各种常用的J2EE设计模式比较熟悉。

   

     图8-55  Launch DTO/Facade Wizard                    图8-56  Facade配置向导

(3)直接单击【Finish】按钮,在EJB模块白板中就出现了该实体Bean对应的会话Bean,即J2EE模式中常见的“会话门面(Session Facade)”模式的操作接口,如图8-57所示。同时工程中生成了一系列的新类,如图8-58所示。

      

              图8-57  会话门面                      图8-58  工程中生成了一系列的新类

(4)找到其中一个ServiceLocator类,修改其中的getInitialContext( )方法如下,修改的内容就是将user和password从null设置为服务器的访问账户,这样可以方便远程访问的实现(实际上本示例用户用不到远程访问)。

代码8.6  ServiceLocator类的getInitialContext( )方法

  public Context getInitialContext() throws Exception {

    String url = "t3://localhost:7001";

       //注意修改该代码,其他不必关心

        String user = "kingbill";

        String password = "22222222";

    Properties properties;

    try {

      properties = new Properties();

      properties.put(Context.INITIAL_CONTEXT_FACTORY,

                     "weblogic.jndi.WLInitialContextFactory");

      properties.put(Context.PROVIDER_URL, url);

      if (user != null) {

        properties.put(Context.SECURITY_PRINCIPAL, user);

        properties.put(Context.SECURITY_CREDENTIALS,

                       password == null ? "" : password);

      }

      return new javax.naming.InitialContext(properties);

    }

    catch (Exception e) {

      System.out.println("Unable to connect to WebLogic server at " + url);

      System.out.println("Please make sure that the server is running.");

      throw e;

    }

  }

前面说到,访问会话门面模式的操作接口是其中的会话Bean,即UserSessionFacade接口,但是实际上并不需要关心这个会话Bean,需要关心的是如下两个类:UserDto和UserDelegate。

1.UserDto类

UserDto类的代码如下。

代码8.7  UserDto.java

package userejb;

import java.io.Serializable;

//只需要看属性和setter/getter方法,其他不必关心

//传输对象必须实现Serializable接口

public class UserDto

    implements Serializable {

  private Integer userId;

  private String username;

  private String password;

  public Integer getUserId() {

    return userId;

  }

  public void setUserId(Integer userId) {

    this.userId = userId;

  }

  public String getUsername() {

    return username;

  }

  public void setUsername(String username) {

    this.username = username;

  }

  public String getPassword() {

    return password;

  }

  public void setPassword(String password) {

    this.password = password;

  }

  public boolean equals(Object obj) {

    if (this == obj) {

      return true;

    }

    if (! (obj instanceof UserDto)) {

      return false;

    }

    UserDto that = (UserDto) obj;

    if (! (that.userId == null ? this.userId == null :

           that.userId.equals(this.userId))) {

      return false;

    }

    if (! (that.username == null ? this.username == null :

           that.username.equals(this.username))) {

      return false;

    }

    if (! (that.password == null ? this.password == null :

           that.password.equals(this.password))) {

      return false;

    }

    return true;

  }

  public int hashCode() {

    int result = 17;

    result = 37 * result + this.userId.hashCode();

    result = 37 * result + this.username.hashCode();

    result = 37 * result + this.password.hashCode();

    return result;

  }

  public String toString() {

    String returnString = "";

    returnString += userId;

    returnString += ", " + username;

    returnString += ", " + password;

    return returnString;

  }

}

2.UserDelegate类

UserDelegate类的代码如下。

代码8.8  UserDelegate.java

package userejb;

public class UserDelegate {

  private UserSessionFacadeHome userSessionFacadeHome;

  private UserSessionFacade userSessionFacade;

  public UserDelegate() throws Exception {

    initializeUserSessionFacadeHome();

    userSessionFacade = userSessionFacadeHome.create();

  }

  //需要关心的CRUD方法

  public void createUser(UserDto userDto) throws Exception {

    userSessionFacade.createUser(userDto);

  }

  public void removeUser(Integer userId) throws Exception {

    userSessionFacade.removeUser(userId);

  }

  public void removeUser(UserDto userDto) throws Exception {

    userSessionFacade.removeUser(userDto);

  }

  public void updateUser(UserDto userDto) throws Exception {

    userSessionFacade.updateUser(userDto);

  }

  public void updateUsers(UserDto[] userDtos) throws Exception {

    userSessionFacade.updateUsers(userDtos);

  }

  public UserDto userFindByPrimaryKey(Integer userId) throws Exception {

    return userSessionFacade.userFindByPrimaryKey(userId);

  }

  public UserDto userFindByUserName(String _username) throws Exception {

    return userSessionFacade.userFindByUserName(_username);

  }

  private void initializeUserSessionFacadeHome() throws Exception {

    String FACADE_NAME = "UserSessionFacade";

    Class FACADE_CLASS = userejb.UserSessionFacadeHome.class;

    if (userSessionFacadeHome == null) {

      try {

        ServiceLocator locator = ServiceLocator.getInstance();

        userSessionFacadeHome = (UserSessionFacadeHome) locator.getEjbHome(

            FACADE_NAME, FACADE_CLASS);

        if (userSessionFacadeHome == null) {

          throw new Exception("Did not get home for " + FACADE_NAME);

        }

      }

      catch (ServiceLocatorException e) {

        throw new Exception(e.getMessage());

      }

    }

  }

}

这两个类同前面章节中的UserDTO类和UserDAO类很相似,最后直接使用这两个类来“连接”到登录示例的代码中,从而实现DAO模式的各个接口。当然,这是为了本书内容的设置要求,实际上在实际的开发中可以直接使用这两个类来完成持久层的功能。

文本框:   
图8-59  编译该工程



8.4.5  部署

接下来要做的是让这个EJB模块提供服务,具体来说,就是编译并且部署到服务器中。这样,只要服务器处于运行状态,各种应用就可以通过本地或者远程的访问,来使用其提供的持久层服务了。具体的步骤如下。

(1)编译。在工程图标上右击,选择【Make】菜单编译该工程,如图8-59所示。如果没有出错,会提示编译成功,如图8-60所示。同时出现一个user.jar文件,如图8-61所示。

(2)部署。在模块图标上右击,选择【Deploy Options for “user.jar”】|【Deploy】菜单

   

                   图8-60  编译成功                               图8-61  user.jar文件

 

               图8-62  部署                                 图8-63  部署成功

部署该模块,如图8-62所示,如果没有出错,会提示部署成功,如图8-63所示。同时在Weblogic控制台界面会出现该模块,如图8-64所示。

图8-64  控制台界面

8.4.6  测试

接下来简单地演示该模块的使用方法,步骤如下。

(1)创建一个测试工程“UserEJBTest”,如图8-65所示。

图8-65  创建测试工程UserEJBTest

(2)选择服务器为Weblogic8.1,如图8-66所示。

(3)将UserEJB工程生成的user.jar导入该工程,如图8-67、图8-68所示。

 

图8-66  选择服务器

图8-67  将user.jar导入该工程

图8-68  将user.jar导入该工程

(4)创建一个测试类UserTest,代码如下。

代码8.9  测试类UserTest.java

import userejb.UserDto;

public class UserTest {

  public static void main(String[] args) {

    try{

    //创建UserDelegate实例

    UserDelegate ud = new UserDelegate();

    //调用CRUD方法

    UserDto u=ud.userFindByUserName("kingbill");

    //输出内容

    System.out.println(u.toString());

    }catch(Exception e){} 

  }

}

(5)这时候会提示UserDelegate类不存在,同时检查user.jar中也不存在该类。JBuilder编译的时候并不将该类同其他类一起打包,因此将UserEJB工程中的UserDelegate类复制到本工程下。这里需要删除package声明,同时导入所有user.jar中的类和接口,代码如下。最后的工程结构如图8-69所示。

代码8.10  复制的UserDelegate.java

//package userejb;

import userejb.*;

public class UserDelegate {

……

}

(6)运行测试类,结果如图8-70所示。

 

         图8-69  工程结构                             图8-70  运行测试类

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论