weblogic ejb3 入门与提高(五)

来源:互联网 发布:react java 哪个好 编辑:程序博客网 时间:2024/05/10 12:38
3.2 有状态会话Bean的生命周期

 其实有状态会话Bean和无状态会话Bean都是有生命周期的,但是,清楚的掌握有状态的会话Bean的生命周期意义更为重要。

 @PostConstruct:当bean对象完成实例化后,使用了这个注释的方法会被立即调用。这个注释同时适用于有状态和无状态的会话bean。
 @PreDestroy:使用这个注释的方法会在容器从它的对象池中销毁一个无用的或者过期的bean 实例之前调用。这个注释同时适用于有状态和无状态的会话bean。
 @PrePassivate:当一个有状态的session bean 实例空闲过长的时间,容器将会钝化(passivate)它,并把它的状态保存在缓存当中。使用这个注释的方法会在容器钝化bean 实例之前调用。这个注释适用于有状态的会话bean。当钝化后,又经过一段时间该bean 仍然没有被操作,容器将会把它从存储介质中删除。以后,任何针对该bean方法的调用容器都会抛出例外。
 @PostActivate:当客户端再次使用已经被钝化的有状态session bean 时,新的实例被创建,状态被恢复。使用此注释的session bean 会在bean 的激活完成时调用。这个注释只适用于有状态的会话bean。
 @Init:这个注释指定了有状态session bean 初始化的方法。它区别于@PostConstruct 注释在于:多个@Init注释方法可以同时存在于有状态session bean 中,但每个bean 实例只会有一个@Init 注释的方法会被调用。这取决于bean 是如何创建的(细节请看EJB 3.0 规范)。@PostConstruct 在@Init 之后被调用。
 另一个有用的生命周期方法注释是@Remove,特别是对于有状态session bean。当应用通过存根对象调用使用了@Remove 注释的方法时,容器就知道在该方法执行完毕后,要把bean 实例从对象池中移走。

 下面我们做一个例子来体验一下有状态会话Bean的生命周期!

 首先新建一个接口。
 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/statefull/TestLifeCycle.java]
 报名:[com.mh.ejb3.test.statefull]
 名称:[TestLifeCycle]
 内容如下:
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.ejb3.test.statefull;

 import java.io.Serializable;

 /**
  * @author moshco zhu
  *
  */
 public interface TestLifeCycle extends Serializable {

  public String sayTest();

  public void remove();

 }
 ----------------------------------------------------------------------
 需要注意的就是:有状态会话Bean是需要实现序列化接口的。

 创建Bean类。
 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/statefull/TestLifeCycleBean.java]
 包名:[com.mh.ejb3.test.statefull]
 名称:[TestLifeCycleBean]
 EJB类型:[有状态会话Bean]
 实现接口:[远程接口]
 内容如下:
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.ejb3.test.statefull;

 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.ejb.Init;
 import javax.ejb.PostActivate;
 import javax.ejb.PrePassivate;
 import javax.ejb.Remote;
 import javax.ejb.Remove;
 import javax.ejb.Stateful;

 /**
  * @author moshco zhu
  *
  */
 @SuppressWarnings("serial")
 @Stateful(mappedName = "TestLifeCycleBean")
 @Remote(TestLifeCycle.class)
 public class TestLifeCycleBean implements TestLifeCycle {

  @Init
  public void ejbCreate() {

   System.out.println("EJB3测试:有状态会话Bean生命周期,生命周期方法被容器调用:[初始化]。");
  }

  @PostConstruct
  public void post() {

   System.out.println("EJB3测试:有状态会话Bean生命周期,生命周期方法被容器调用:[初始化后的内容初始化]。");

  }

   @PrePassivate
   public void passivate() {
  
   System.out.println("EJB3测试:有状态会话Bean生命周期,生命周期方法被容器调用:[EJB处于钝化状态]。");
  
   }
  
   @PostActivate
   public void postActivate() {
  
   System.out.println("EJB3测试:有状态会话Bean生命周期,生命周期方法被容器调用:[EJB处于钝化激活状态]。");
  
   }

  @Remove
  public void remove() {

   System.out.println("EJB3测试:有状态会话Bean生命周期,生命周期方法被容器调用:[EJB将被删除]。");

  }

   @PreDestroy
   public void destroy() {
  
   System.out.println("EJB3测试:有状态会话Bean生命周期,生命周期方法被容器调用:[EJB处于销毁状态]。");
   }

  /*
   * (非 Javadoc)
   *
   * @see com.mh.ejb3.test.statefull.TestLifeCycle#sayTest()
   */
  public String sayTest() {

   String strResult = "EJB3测试:有状态会话Bean的生命周期!业务方法被调用了!";

   return strResult;
  }

 }
 ----------------------------------------------------------------------
 这个EJB的JNDI应该是:[TestLifeCycleBean#com.mh.ejb3.test.statefull.TestLifeCycle]。
 这里有个地方是要特别注意一下,就是:[@Init]定义的方法的名称在Weblogic中必须是[ejbCreate],而且可以有多个,就像EJB的构造方法一样,容器会通用哪个,是由调用者决定的。

 下面写访问的Servlet,打开文件[WebContext/JavaSource/com/mh/servlet/test/CommonSV.java],添加下面一段:
 ----------------------------------------------------------------------
 } else if (strPara != null && strPara.equals("TestLifeCycle")) {
  // 通过JNDI获取EJB对象
  TestLifeCycle test = (TestLifeCycle) getEJBObject("TestLifeCycleBean#com.mh.ejb3.test.statefull.TestLifeCycle");
  message += test.sayTest() + "/n<br>";
  message += "这是一个关于有状态会话Bean的生命周期的例子!你注意观察控制台!";

  // 把会话Bean保存到session中
  HttpSession session = request.getSession(true);
  session.setAttribute("TestLifeCycle", test);
 } else if (strPara != null && strPara.equals("RemoveTestLifeCycle")) {
  // 通过JNDI获取EJB对象

  // 从session中取出之前的session Bean
  HttpSession session = request.getSession(true);
  TestLifeCycle test = (TestLifeCycle) session
    .getAttribute("TestLifeCycle");
  test.remove();

  message += "删除有状态会话Bean完成!/n<br>";
  message += "这是一个关于有状态会话Bean的生命周期的例子!你注意观察控制台!";
 ----------------------------------------------------------------------

 在欢迎页面程序[WebContext/index.jsp],加入下面这段:
 ----------------------------------------------------------------------
 <p><center>
 EJB3测试:有状态会话Bean生命周期的例子<br>
 <a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=TestLifeCycle" target="_blank">创建一个有状态会话Bean</a><br>
 <a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=RemoveTestLifeCycle" target="_blank">删除当前的有状态会话Bean</a><br>
 </center></p>
 ----------------------------------------------------------------------

 编译发布程序,等一会你就可以看效果了!

 如果发布的过程中,你遇到一些奇怪的问题,比如什么不能发布,或者能发布却不能激活,你可以打开你的电脑的任务管理器,看一看有没有一个叫[bea...](后面部分不记得了)的进程,把它Kill,问题就解决了!这个是花费了我近2天的时间才发现的。

 weblogic中,一个有状态会话Bean对象在容器中如果10分钟不被使用,它会被容器放人硬盘缓存,处于钝化状态;如果再过一段时间不被使用,它会被容器容器删除;如果中间有调用,它就会激活.

 

4.配置数据源
 
 我这里使用的数据库是MySQL,版本是:5.0.37。下载安装的过程我就不多说了!我使用的客户端软件是:phpMyAdmin 2.10.0.2。如果能熟练使用MySQL命令,也可以不使用这个软件。

 下载安装完成MySQL后,创建一个数据库,名称[ejb3],在数据库中创建一个表[user],表的结构如下:
 --------------------------------------------------
 字段  数据类型 是否可为空  其它   备注
 id  int  否   auto_increment  记录编号
 Name  varchar(64) 否      姓名
 --------------------------------------------------

 向表[user]中插入几条记录,至少要有一条[id=1]的,等会程序会搜索这条记录。

 启动weblogic服务,打开控制中心。

 进入[Domain Structure]->[Services]->[JDBC]->[Data Sources],然后点击左上角的[lock &Edit],然后点击[new],创建一个新的数据源,设置[name="mysql_ejb31"]、[JNDI name = "mysql_ejb31"]、[Database Type ="MySQL"]、[Database Driver="com.mysql.jdbc.Driver"],然后点击[Next]按钮,再次点击[Next],[Database Name="ejb3"]、[Database Name="localhost"]、[Port="3306"]、[Database User Name ="root"](这个要根据你自己的实际情况来填写),[Password=""][Confirm Password=""](这两个也要根据你的实际情况填写)、然后点击[Next],点击[Test Configuration],测试一下我们的配置,如果上面显示成功,我们要继续点击[Next],然后构选服务器[AdminServer],点击[Finish],最好点击左上角的[Activate Changes]。这样就算配置完成了!

 做完上面的操作,你可以打开服务器[AdminServer]的JNDI树,看一下是否多了一个[mysql_ejb31]。

 好!下面我们做一个程序来使用这个数据源。

 首先创建一个工具类。
 文件地址:[Java/JavaSource/com/mh/util/DSUtil.java]
 包名:[com.mh.util]
 名称:[DSUtil]
 内容如下:
 ---------------------------------------------------------------------
 /**
  *
  */
 package com.mh.util;

 import java.util.Properties;

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

 /**
  * @author moshco zhu
  *
  */
 public class DSUtil {

  public static String Host = "localhost";
  static {
   Host = "localhost";
  }

  /**
   * @功能 获取EJB对象从默认的应用服务器
   *
   * @param strJNDI
   * @return
   * @throws Exception
   */
  public static DataSource getDSObject(String strJNDI) throws Exception {

   // 创建属性对象
   Properties props = new Properties();
   props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
     "weblogic.jndi.WLInitialContextFactory");
   props.setProperty(Context.PROVIDER_URL, "t3://" + Host + ":7001");

   // 创建上下文环境对象
   InitialContext ctx;
   ctx = new InitialContext(props);

   // 远程计算机
   DataSource oDS = (DataSource) ctx.lookup(strJNDI);

   // 返回函数值
   return oDS;
  }

  /**
   * @功能 获取本地EJB对象
   *
   * @param strJNDI
   * @return
   * @throws Exception
   */
  public static DataSource getDSLocalObject(String strJNDI) throws Exception {

   // 创建上下文环境对象
   InitialContext ctx;
   ctx = new InitialContext();

   // 本地电脑
   DataSource oDS = (DataSource) ctx.lookup(strJNDI);

   // 返回函数值
   return oDS;
  }

 }
 ---------------------------------------------------------------------
 这个类的作用主要是获取一个数据源,以后扩展它的功能,还可以用来管理多个数据源。
 
 下面创建一个接口程序。
 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/EJB3TestDBConnection.java]
 包名:[com.mh.ejb3.test]
 名称:[EJB3TestDBConnection]
 内容如下:
 ---------------------------------------------------------------------
 /**
  *
  */
 package com.mh.ejb3.test;

 /**
  * @author moshco zhu
  *
  */
 public interface EJB3TestDBConnection {
  
  public String sayTest();

 }
 ---------------------------------------------------------------------

 创建EJB的Bean类。
 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/EJB3TestDBConnectionBean.java]
 包名:[com.mh.ejb3.test]
 名称:[EJB3TestDBConnectionBean]
 EJB类型:无状态会话Bean
 实现接口:远程接口
 内容如下:
 ---------------------------------------------------------------------
 /**
  *
  */
 package com.mh.ejb3.test;

 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;

 import javax.ejb.Remote;
 import javax.ejb.Stateless;
 import javax.sql.DataSource;

 import com.mh.util.DSUtil;

 /**
  * @author moshco zhu
  *
  */
 @Stateless(mappedName = "EJB3TestDBConnectionBean")
 @Remote(EJB3TestDBConnection.class)
 public class EJB3TestDBConnectionBean implements EJB3TestDBConnection {

  /*
   * (非 Javadoc)
   *
   * @see com.mh.ejb3.test.EJB3TestDBConnection#sayTest()
   */
  public String sayTest() {

   // 定义变量
   DataSource ds = null;
   Connection conn = null;
   String strMessage = "";

   try {

    // 获取数据源
    ds = DSUtil.getDSObject("mysql_ejb31");
    // 获取数据库连接
    conn = ds.getConnection();
    if (conn != null && !conn.isClosed()) {
     strMessage += "数据库连接成功!/n<br>";
    }

    // 查询用户名
    PreparedStatement pre = conn
      .prepareStatement("select Name from user where id = 1");
    ResultSet rs = pre.executeQuery();

    // 获取数据
    while (rs.next()) {
     strMessage += "Hello,";
     strMessage += rs.getString("Name") + "!/n<br>";
     break;
    }

   } catch (Exception e) {
    e.printStackTrace();
    strMessage += "出错了:[" + e.toString() + "]/n<br>";
   } finally {
    try {
     if (conn != null && !conn.isClosed()) {
      conn.close();
      conn = null;
     }
    } catch (SQLException e) {
     e.printStackTrace();
    }
    ds = null;
   }

   // 返回函数值
   return strMessage;
  }

 }
 ---------------------------------------------------------------------
 上面的程序,通过数据库的JNDI获取数据源,进而获取数据库连接,最后查询数据库表,获取用户名。

 打开文件[WebContext/JavaSource/com/mh/servlet/test/CommonSV.java],我们在servelt中加入下面这段:
 ---------------------------------------------------------------------
   } else if (strPara != null
     && strPara.equals("EJB3TestDBConnection")) {
    // 通过JNDI获取EJB对象
    EJB3TestDBConnection test = (EJB3TestDBConnection) getEJBObject("EJB3TestDBConnectionBean#com.mh.ejb3.test.EJB3TestDBConnection");
    message += test.sayTest();
 ---------------------------------------------------------------------
 
 在欢迎页面程序[WebContext/index.jsp]中加入下面这段:
 ---------------------------------------------------------------------
 <p>
 <center><a
  href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=EJB3TestDBConnection"
  target="_blank">EJB3测试:使用数据库</a></center>
 </p>
 ---------------------------------------------------------------------
 
 好!现在可以编译发布看效果了!

 

5.访问EJB3

 我们常用于访问EJB的可能有如下几种:
 1.EJB调用远程或本地JVM的EJB;
 2.Servlet访问远程或本地JVM的EJB;
 3.普通Java类也可以调用远程JVM的EJB;
 注意:这里的远程不一定是另外一台电脑。同一台电脑,如果一个是weblogic服务器,一个是运行中的普通Java类,它们也不是在同一个JVM中。

 weblogic server中,EJB3提供的访问方式有:
 1.使用标签配置JNDI,然后使用这个JNDI访问EJB对象;
 2.在同一个JVM中,使用依赖注入的方式访问本地容器中的EJB对象;
 3.在配置文件中引用EJB,然后使用JNDI访问。

 下面我对各种访问方式分别做一个例子。

 5.1 使用标签配置JNDI,然后使用这个JNDI访问EJB对象

 这种访问方式是EJB3最明显的特性。正是因为大量使用标签,EJB3的开发才大大降低了繁琐度、难度,使开发一个EJB变得十分简单和有趣。

 下面我们设想一种业务需求来完成这种访问方式的演示。
 需求:用户账户有多条资金交易记录,现在把它查询列表显示,并提供每条记录的明细。
 设计:设计一个EJB用来操作用户账户交易记录,实现两个功能:模糊查询显示列表,根据ID查询显示详细;
 观察:EJB的JNDI采用标签配置。

 
 第一要做的是创建数据库表,我是在MySQL中实现的,表的数据结构如下:
 表名:[traderecord]
 ----------------------------------------------------------------------
   字段  数据类型   编码类型 可否为空 默认值  自动增加  描述
 ----------------------------------------------------------------------
   Id  int(11)      否    auto_increment  记录编号
   TradeType varchar(32)   gbk_bin  否       业务类型
   TimeBegin datetime     否       开始时间
   GoodsName varchar(256)   gbk_bin  是  NULL     货品名称
   GoodsInfo varchar(1024)   gbk_bin  是  NULL     货品信息
   Money  float      是  NULL     总金额
   MoneyInfo varbinary(1024)     否       金额信息
   TradePoint varchar(8) gbk_bin    否       交易方向
   User  varbinary(64)     否       用户
   Comrade varchar(64) gbk_bin    是  NULL     交易伙伴
   State  varchar(8) gbk_bin    否       状态
   Remark varchar(1024) gbk_bin    是  NULL     备注
 ---------------------------------------------------------------------- 


 我们创建两个业务Java Bean的类,这两个Bean类的主要作用是封装数据,数据格式标准化转换,这两个Java Bean类是继承一个基础Java Bean类。

 基础Java Bean类。
 文件地址:[Java/JavaSource/com/mh/javabean/CommondBean.java]
 包路径:[com.mh.javabean]
 名称:[CommondBean]
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.javabean;

 import java.io.Serializable;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;

 /**
  * @author moshco zhu
  *
  */
 @SuppressWarnings("serial")
 public class CommondBean implements Serializable {

  /**
   * @描述:将Bean数组转化为XML字符串
   * @param bean
   * @return
   * @throws InvocationTargetException
   * @throws IllegalAccessException
   * @throws IllegalArgumentException
   */
  public static String toXML(CommondBean[] aBean)
    throws IllegalArgumentException, IllegalAccessException,
    InvocationTargetException {

   // 定义变量
   String strResult = "";

   // Bean数组对象不能为空
   if (aBean == null) {
    return "";
   }

   // xml头字符串
   strResult += "<?xml version=/"1.0/" encoding=/"UTF-8/"?>/n";
   strResult += "<beans name=/"TradeRecordList/">/n";
   // 逐一处理数组中每一个Bean对象
   for (int i = 0; i < aBean.length; i++) {
    // 获取Bean对象
    CommondBean bean = aBean[i];
    strResult += bean.getBeanXML();
   }
   strResult += "</beans>";

   // 返回函数值
   return strResult;
  }

  /**
   * @描述:将Bean对象转换为XML字符串
   * @param bean
   * @return
   * @throws InvocationTargetException
   * @throws IllegalAccessException
   * @throws IllegalArgumentException
   */
  public static String toXML(CommondBean bean)
    throws IllegalArgumentException, IllegalAccessException,
    InvocationTargetException {

   // 定义变量
   String strResult = "";

   // Bean数组对象不能为空
   if (bean == null) {
    return "";
   }

   // xml头字符串
   strResult += "<?xml version=/"1.0/" encoding=/"UTF-8/"?>/n";
   strResult += "<beans name=/"TradeRecordList/">/n";
   // 获取Bean对象
   strResult += bean.getBeanXML();
   strResult += "</beans>";

   // 返回函数值
   return strResult;
  }

  /**
   * @描述:获取Bean的XML字符串
   * @return
   * @throws InvocationTargetException
   * @throws IllegalAccessException
   * @throws IllegalArgumentException
   */
  public String getBeanXML() throws IllegalArgumentException,
    IllegalAccessException, InvocationTargetException {

   // 定义变量
   String strResult = "";

   // 获取Bean对象的字段数组
   Field[] aFld = this.getClass().getDeclaredFields();
   if (aFld == null || aFld.length == 0) {
    return "";
   }

   // 获取Bean对象的方法数组
   Method[] aMth = this.getClass().getDeclaredMethods();
   if (aMth == null || aMth.length == 0) {
    return "";
   }

   // 开始组合:执行每一个有get方法、set方法的字段
   for (int i = 0; i < aFld.length; i++) {

    // 获取字段的名称
    String strFildName = aFld[i].getName();
    String strNameGet = ("get" + strFildName).toLowerCase();
    String strNameSet = ("set" + strFildName).toLowerCase();

    // 寻找get、set方法的标识
    boolean bGet = false;
    boolean bSet = false;

    // Get方法的位置
    int iGet = -1;

    // 搜索所有的方法
    for (int j = 0; j < aMth.length; j++) {
     // 匹配Get方法
     if (strNameGet.equals(aMth[j].getName().toLowerCase())) {
      bGet = true;
      iGet = j;
     }
     // 匹配Set方法
     if (strNameSet.equals(aMth[j].getName().toLowerCase())) {
      bSet = true;
     }
     if (bGet && bSet) {
      break;
     }
    }

    // 组合XML字符串
    if (bGet && bSet && iGet >= 0) {
     strResult += "/t/t<field name=/"" + strFildName + "/">";
     Object[] aO = null;
     Object oResult = aMth[iGet].invoke(this, aO);
     if (oResult != null) {
      strResult += oResult.toString();
     }
     strResult += "</field>/n";
    }
   }
   
   if(strResult != null && strResult.length() > 0){
    strResult = "/t<bean>/n"+strResult+ "/t</bean>/n";
   }

   // 返回函数值
   return strResult;
  }

 }
 ----------------------------------------------------------------------
 这个Bean类的作用,主要是将Bean类数据转换为XML字符串。它是一个Bean类的基础类,可以在这个类里面扩展一些JavaBean公用和基础的功能。
 这里我们主要实现了三个功能:
  public static String toXML(CommondBean[] aBean):将Bean对象数组转换为标准的XML文件格式字符串;
  public static String toXML(CommondBean bean):将Bean对象转换为标准的XML文件格式字符串;
  public String getBeanXML():将Bean本自己转换为标准XML字符串。


 第一个Java Bean类。
 文件地址:[Java/JavaSource/com/mh/ejb3/test/javabean/TradeRecord.java]
 包路径:[com.mh.ejb3.test.javabean]
 名称:[TradeRecord]
 具体内容如下:
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.ejb3.test.javabean;

 import java.io.Serializable;
 import java.sql.Timestamp;

 import com.mh.javabean.CommondBean;

 /**
  * @author moshco zhu
  *
  */
 @SuppressWarnings("serial")
 public class TradeRecord extends CommondBean {

  private int Id = -1;

  private String TradeType = null;

  private Timestamp TimeBegin = null;

  private String GoodsName = null;

  private String GoodsInfo = null;

  private String Money = null;

  private String MoneyInfo = null;

  private String TradePoint = null;

  private String User = null;

  private String Comrade = null;

  private String State = null;

  private String Remark = null;

  /**
   * @return remark
   */
  public String getRemark() {
   return Remark;
  }

  /**
   * @param remark
   *            要设置的 remark
   */
  public void setRemark(String remark) {
   Remark = remark;
  }

  /**
   * @return comrade
   */
  public String getComrade() {
   return Comrade;
  }

  /**
   * @param comrade
   *            要设置的 comrade
   */
  public void setComrade(String comrade) {
   Comrade = comrade;
  }

  /**
   * @return goodsInfo
   */
  public String getGoodsInfo() {
   return GoodsInfo;
  }

  /**
   * @param goodsInfo
   *            要设置的 goodsInfo
   */
  public void setGoodsInfo(String goodsInfo) {
   GoodsInfo = goodsInfo;
  }

  /**
   * @return goodsName
   */
  public String getGoodsName() {
   return GoodsName;
  }

  /**
   * @param goodsName
   *            要设置的 goodsName
   */
  public void setGoodsName(String goodsName) {
   GoodsName = goodsName;
  }

  /**
   * @return id
   */
  public int getId() {
   return Id;
  }

  /**
   * @param id
   *            要设置的 id
   */
  public void setId(int id) {
   Id = id;
  }

  /**
   * @return money
   */
  public String getMoney() {
   return Money;
  }

  /**
   * @param money
   *            要设置的 money
   */
  public void setMoney(String money) {
   Money = money;
  }

  /**
   * @return moneyInfo
   */
  public String getMoneyInfo() {
   return MoneyInfo;
  }

  /**
   * @param moneyInfo
   *            要设置的 moneyInfo
   */
  public void setMoneyInfo(String moneyInfo) {
   MoneyInfo = moneyInfo;
  }

  /**
   * @return state
   */
  public String getState() {
   return State;
  }

  /**
   * @param state
   *            要设置的 state
   */
  public void setState(String state) {
   State = state;
  }

  /**
   * @return timeBegin
   */
  public Timestamp getTimeBegin() {
   return TimeBegin;
  }

  /**
   * @param timeBegin
   *            要设置的 timeBegin
   */
  public void setTimeBegin(Timestamp timeBegin) {
   TimeBegin = timeBegin;
  }

  /**
   * @return tradePoint
   */
  public String getTradePoint() {
   return TradePoint;
  }

  /**
   * @param tradePoint
   *            要设置的 tradePoint
   */
  public void setTradePoint(String tradePoint) {
   TradePoint = tradePoint;
  }

  /**
   * @return tradeType
   */
  public String getTradeType() {
   return TradeType;
  }

  /**
   * @param tradeType
   *            要设置的 tradeType
   */
  public void setTradeType(String tradeType) {
   TradeType = tradeType;
  }

  /**
   * @return user
   */
  public String getUser() {
   return User;
  }

  /**
   * @param user
   *            要设置的 user
   */
  public void setUser(String user) {
   User = user;
  }

 }
 ----------------------------------------------------------------------
 TradeRecord类的主要作用是封装交易记录完整信息。


 第二个Java Bean类。
 文件地址:[Java/JavaSource/com/mh/ejb3/test/javabean/TradeRecordList.java]
 包路径:[com.mh.ejb3.test.javabean]
 名称:[TradeRecordList]
 具体内容如下:
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.ejb3.test.javabean;

 import java.io.Serializable;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.sql.Timestamp;

 import com.mh.javabean.CommondBean;

 /**
  * @author moshco zhu
  *
  */
 @SuppressWarnings("serial")
 public class TradeRecordList extends CommondBean{

  private int Id = -1;

  private String TradeType = null;

  private Timestamp TimeBegin = null;

  private String GoodsName = null;

  private String Money = null;

  private String TradePoint = null;

  private String Comrade = null;

  private String State = null;

  /**
   * @return comrade
   */
  public String getComrade() {
   return Comrade;
  }

  /**
   * @param comrade
   *            要设置的 comrade
   */
  public void setComrade(String comrade) {
   Comrade = comrade;
  }

  /**
   * @return goodsName
   */
  public String getGoodsName() {
   return GoodsName;
  }

  /**
   * @param goodsName
   *            要设置的 goodsName
   */
  public void setGoodsName(String goodsName) {
   GoodsName = goodsName;
  }

  /**
   * @return id
   */
  public int getId() {
   return Id;
  }

  /**
   * @param id
   *            要设置的 id
   */
  public void setId(int id) {
   Id = id;
  }

  /**
   * @return money
   */
  public String getMoney() {
   return Money;
  }

  /**
   * @param money
   *            要设置的 money
   */
  public void setMoney(String money) {
   Money = money;
  }

  /**
   * @return state
   */
  public String getState() {
   return State;
  }

  /**
   * @param state
   *            要设置的 state
   */
  public void setState(String state) {
   State = state;
  }

  /**
   * @return timeBegin
   */
  public Timestamp getTimeBegin() {
   return TimeBegin;
  }

  /**
   * @param timeBegin
   *            要设置的 timeBegin
   */
  public void setTimeBegin(Timestamp timeBegin) {
   TimeBegin = timeBegin;
  }

  /**
   * @return tradePoint
   */
  public String getTradePoint() {
   return TradePoint;
  }

  /**
   * @param tradePoint
   *            要设置的 tradePoint
   */
  public void setTradePoint(String tradePoint) {
   TradePoint = tradePoint;
  }

  /**
   * @return tradeType
   */
  public String getTradeType() {
   return TradeType;
  }

  /**
   * @param tradeType
   *            要设置的 tradeType
   */
  public void setTradeType(String tradeType) {
   TradeType = tradeType;
  }

 }
 ----------------------------------------------------------------------
 TradeRecordList类的作用主要是封装交易记录用来列表显示的信息。

 到这里已经完成了数据模型的创建,接下来创建数据操作层DAO类。

 创建DAO类。
 文件地址:[Java/JavaSource/com/mh/dao/test/TradeRecordDAO.java]
 包名:[com.mh.dao.test]
 名称:[TradeRecordDAO]
 内容如下:
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.dao.test;

 import java.io.Serializable;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;

 import javax.sql.DataSource;

 import com.mh.ejb3.test.javabean.TradeRecord;
 import com.mh.ejb3.test.javabean.TradeRecordList;
 import com.mh.util.DSUtil;

 /**
  * @author moshco zhu
  *
  */
 @SuppressWarnings("serial")
 public class TradeRecordDAO implements Serializable {

  /**
   * @描述:定义成员变量
   *
   */
  private DataSource ds = null;

  private Connection conn = null;

  /**
   * @描述:构造函数
   *
   */
  public TradeRecordDAO() {

   // 获取数据源
   try {

    // 获取数据源对象
    ds = DSUtil.getDSObject("mysql_ejb31");
    // 获取数据库连接
    conn = ds.getConnection();
   } catch (Exception e) {
    e.printStackTrace();
   }

  }

  /**
   * @描述:获取指定的Bean对象
   * @param iId
   * @return
   */
  public TradeRecord findTradeRecord(int iId) {

   // 获取数据源
   TradeRecord bean = null;

   try {

    // 查询数据
    String strSQL = "";
    strSQL += "select ";
    strSQL += "  Id,";
    strSQL += "  TradeType,";
    strSQL += "  TimeBegin,";
    strSQL += "  GoodsName,";
    strSQL += "  GoodsInfo,";
    strSQL += "  Money,";
    strSQL += "  MoneyInfo,";
    strSQL += "  TradePoint,";
    strSQL += "  User,";
    strSQL += "  Comrade,";
    strSQL += "  State,";
    strSQL += "  Remark ";
    strSQL += "from ";
    strSQL += "  TradeRecord ";
    strSQL += "where ";
    strSQL += "  Id = ?";
    PreparedStatement psta = conn.prepareStatement(strSQL);
    psta.setInt(1, iId);
    ResultSet rs = psta.executeQuery();

    // 获取结果
    while (rs.next()) {
     // 创建Bean对象
     bean = new TradeRecord();
     bean.setId(rs.getInt("Id"));
     bean.setTradeType(rs.getString("TradeType"));
     bean.setTimeBegin(rs.getTimestamp("TimeBegin"));
     bean.setGoodsName(rs.getString("GoodsName"));
     bean.setGoodsInfo(rs.getString("GoodsInfo"));
     bean.setMoney(rs.getString("Money"));
     bean.setMoneyInfo(rs.getString("MoneyInfo"));
     bean.setTradePoint(rs.getString("TradePoint"));
     bean.setUser(rs.getString("User"));
     bean.setComrade(rs.getString("Comrade"));
     bean.setState(rs.getString("State"));
     bean.setRemark(rs.getString("Remark"));
     // 中断
     break;
    }

   } catch (Exception e) {
    e.printStackTrace();
   } finally {
    try {
     if (conn != null && !conn.isClosed()) {
      conn.close();
      conn = null;
     }
    } catch (SQLException e) {
     e.printStackTrace();
    }
    ds = null;
   }

   // 返回函数值
   return bean;
  }

  @SuppressWarnings("unchecked")
  public TradeRecordList[] queryUnsharp(String strKeyWord) {

   // 获取数据源
   List lstTradeRecord = new ArrayList();
   TradeRecordList bean = null;
   TradeRecordList[] aBean = null;

   try {

    // 查询数据
    String strSQL = "";
    strSQL += "select ";
    strSQL += "  Id,";
    strSQL += "  TradeType,";
    strSQL += "  TimeBegin,";
    strSQL += "  GoodsName,";
    strSQL += "  Money,";
    strSQL += "  TradePoint,";
    strSQL += "  Comrade,";
    strSQL += "  State ";
    strSQL += "from ";
    strSQL += "  TradeRecord ";
    strSQL += "where ";
    strSQL += "  GoodsName like concat('%',concat(?,'%'))";
    strSQL += "  or Comrade like concat('%',concat(?,'%'))";
    PreparedStatement psta = conn.prepareStatement(strSQL);
    psta.setString(1, strKeyWord);
    psta.setString(2, strKeyWord);
    ResultSet rs = psta.executeQuery();

    // 获取结果
    while (rs.next()) {
     // 创建Bean对象
     bean = new TradeRecordList();
     bean.setId(rs.getInt("Id"));
     bean.setTradeType(rs.getString("TradeType"));
     bean.setTimeBegin(rs.getTimestamp("TimeBegin"));
     bean.setGoodsName(rs.getString("GoodsName"));
     bean.setMoney(rs.getString("Money"));
     bean.setTradePoint(rs.getString("TradePoint"));
     bean.setComrade(rs.getString("Comrade"));
     bean.setState(rs.getString("State"));
     // 加入数组
     lstTradeRecord.add(bean);
    }

    // 转换为数组
    if (lstTradeRecord != null && lstTradeRecord.size() > 0) {
     aBean = new TradeRecordList[lstTradeRecord.size()];
     aBean = (TradeRecordList[]) lstTradeRecord.toArray(aBean);
    }

   } catch (Exception e) {
    e.printStackTrace();
   } finally {
    try {
     if (conn != null && !conn.isClosed()) {
      conn.close();
      conn = null;
     }
    } catch (SQLException e) {
     e.printStackTrace();
    }
    ds = null;
   }

   // 返回函数值
   return aBean;
  }
 }

 ----------------------------------------------------------------------
 这个DAO类实现的功能主要是:
 public TradeRecordDAO():构造函数,用来获取数据源,DSUtil类的内容在上一篇文件中已经讲过了。需要注意的是数据源JNDI[mysql_ejb31]的配置大家要根据实际情况来写。
 public TradeRecord findTradeRecord(int iId):根据记录Id,查找相关Bean对象。
 public TradeRecordList[] queryUnsharp(String strKeyWord):通过关键字查询所有服务要求的Bean对象列表。


 下面介绍业务逻辑层的编写。

 首先编写EJB。
 接口类。

 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/labeljndi/TradeRecordManage.java]
 包名:[com.mh.ejb3.test.labeljndi]
 名称:[TradeRecordManage]
 内容如下:
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.ejb3.test.labeljndi;

 import com.mh.ejb3.test.javabean.TradeRecord;
 import com.mh.ejb3.test.javabean.TradeRecordList;

 /**
  * @author moshco zhu
  *
  */
 public interface TradeRecordManage {

  public TradeRecordList[] queryUnsharp(String strKeyWord);

  public TradeRecord findTradeRecord(int iId);

 }
 ----------------------------------------------------------------------
 

 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/labeljndi/TradeRecordManageBean.java]
 包名:[com.mh.ejb3.test.labeljndi]
 名称:[TradeRecordManageBean]
 EJB类型:无状态会话Bean
 实现业务接口:远程接口
 内容如下:
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.ejb3.test.labeljndi;

 import javax.ejb.Remote;
 import javax.ejb.Stateless;

 import com.mh.dao.test.TradeRecordDAO;
 import com.mh.ejb3.test.javabean.TradeRecord;
 import com.mh.ejb3.test.javabean.TradeRecordList;

 /**
  * @author moshco zhu
  *
  */
 @Stateless(mappedName = "TradeRecordManageBean")
 @Remote(TradeRecordManage.class)
 public class TradeRecordManageBean implements TradeRecordManage {

  /*
   * (非 Javadoc)
   *
   * @see com.mh.ejb3.test.labeljndi.TradeRecordManage#findTradeRecord(int)
   */
  public TradeRecord findTradeRecord(int iId) {

   // 创建DAO对象
   TradeRecordDAO dao = new TradeRecordDAO();

   // 实现业务操作
   TradeRecord bean = dao.findTradeRecord(iId);

   // 返回函数值
   return bean;
  }

  /*
   * (非 Javadoc)
   *
   * @see com.mh.ejb3.test.labeljndi.TradeRecordManage#queryUnsharp(java.lang.String)
   */
  public TradeRecordList[] queryUnsharp(String strKeyWord) {

   // 创建DAO对象
   TradeRecordDAO dao = new TradeRecordDAO();

   // 实现业务操作
   TradeRecordList[] aBean = dao.queryUnsharp(strKeyWord);

   // 返回函数值
   return aBean;
  }

 }
 ----------------------------------------------------------------------
 EJB实现了两个功能:[findTradeRecord]和[findTradeRecord],一个是显示详细Bean数据,一个是显示模糊查询的列表。
 需要注意的是,我们这里采用的是通过注解来定义EJB的JNDI,根据[@Stateless(mappedName = "TradeRecordManageBean")],我们可以确定JNDI应该是[TradeRecordManageBean@com.mh.ejb3.test.labeljndi.TradeRecordManage],[@]后面的部分是EJB的接口全名称。


 接下来我们编写,逻辑控制层Servlet的代码。
 文件地址:[WebContext/JavaSource/com/mh/servlet/test/pay/TradeRecordSV.java]
 包名:[com.mh.servlet.test.pay]
 名称:[TradeRecordSV]
 内容如下:
 ----------------------------------------------------------------------
 /**
  *
  */
 package com.mh.servlet.test.pay;

 import java.io.IOException;
 import java.io.PrintWriter;

 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;

 import com.mh.ejb3.test.javabean.TradeRecord;
 import com.mh.ejb3.test.javabean.TradeRecordList;
 import com.mh.ejb3.test.labeljndi.TradeRecordManage;
 import com.mh.util.EJBUtil;

 /**
  * @author moshco zhu
  *
  */
 @SuppressWarnings("serial")
 public class TradeRecordSV extends HttpServlet {

  @Override
  public void init() throws ServletException {
   // TODO 自动生成方法存根
   super.init();
  }

  @Override
  public void destroy() {
   // TODO 自动生成方法存根
   super.destroy();
  }

  @Override
  protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
   doWork(request, response);
  }

  @Override
  protected void doPost(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
   doWork(request, response);
  }

  /**
   * @描述:公共处理方法
   *
   * @param strJNDI
   * @return
   * @throws Excep
   */
  private void doWork(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

   // 获取输出对象
   request.setCharacterEncoding("UTF-8");
   response.setCharacterEncoding("UTF-8"); // 设置输出编码
   response.setContentType("text/XML;charset=UTF-8");
   PrintWriter out = response.getWriter();
   // 结果值
   String message = "Test:<br><hr size='1'>";

   try {

    // 获取参数
    String strPara = (String) request.getParameter("dowith");

    if (strPara != null && strPara.equals("queryUnsharp")) {

     // 通过JNDI获取EJB对象
     TradeRecordManage ejbDB = (TradeRecordManage) EJBUtil
       .getEJBObject("TradeRecordManageBean#com.mh.ejb3.test.labeljndi.TradeRecordManage");

     // 模糊查询
     String strKeyWord = request.getParameter("keyword");
     TradeRecordList[] aBean = ejbDB.queryUnsharp(strKeyWord);

     // Bean数组转换为XML字符串
     message = TradeRecordList.toXML(aBean);

    } else if (strPara != null && strPara.equals("findTradeRecord")) {

     // 通过JNDI获取EJB对象
     TradeRecordManage ejbDB = (TradeRecordManage) EJBUtil
       .getEJBObject("TradeRecordManageBean#com.mh.ejb3.test.labeljndi.TradeRecordManage");

     // 查询Bean对象
     int iId = Integer.parseInt(request.getParameter("id"));
     TradeRecord bean = ejbDB.findTradeRecord(iId);

     // Bean数组转换为XML字符串
     message = TradeRecord.toXML(bean);

    }

   } catch (Exception e) {
    e.printStackTrace();
    message += e.toString();
   } finally {
   }

   // 输出
   out.print(message);
   out.flush();
   out.close();
  }

 }
 ----------------------------------------------------------------------
 上面的Servlet中,我们提交请求后返回的是XML标准文件字符串,主要是通过基础Bean类的[toXML]方法来转换的,之所以把他转换为XML字符串,是因为在js中可以使用不同的样式表来显示不同的样式。需要提醒一下的是,上面有一段是这样写的[response.setContentType("text/XML;charset=UTF-8");],这是在告诉Servlet返回数据类型应该是text和xml格式,如果是HTML格式应该写成:[response.setContentType("text/html;charset=UTF-8");]。

 因为创建了新的Servlet,所以,我们要在[web.xml]中加以定义。
 打开文件[WebContext/WEB-INF/web.xml],添加下面这段:
 ----------------------------------------------------------------------
  <!-- 定义一个Servlet -->
  <servlet>
   <servlet-name>TradeRecordSV</servlet-name>
   <servlet-class>
    com.mh.servlet.test.pay.TradeRecordSV
   </servlet-class>
   <load-on-startup>4</load-on-startup>
  </servlet>
  <servlet-mapping>
   <servlet-name>TradeRecordSV</servlet-name>
   <url-pattern>/sv/TradeRecordSV.do</url-pattern>
  </servlet-mapping>
 ----------------------------------------------------------------------

 

原创粉丝点击