EJB学习之SessionBean(会话Bean)

那么首先我们要讲到的是SessionBean就是会话Bean。

在MVC模型当中,J2EE程序通常是以JSP来充当显示层、Servlet来充当控制层、JavaBean用来充当模型层。当我们使用EJB体系后,模型层就使用EJB组件来充当。

模型层也就是用来处理业务逻辑,而业务逻辑在系统中可简单的分为两类:

一、信息处理和流程控制

二、数据库操作

而我们所要讲到的SessionBean就是用来处理信息和流程控制的。

会话Bean表示为业务进程,一般用来封装企业应用的业务逻辑。比如:计算购买总价,货币利率转换等等。

根据会话Bean的类型我们可以把它分为两类:

一、无状态会话Bean

二、有状态会话Bean

无状态会话Bean,主要是用来处理单纯的业务逻辑。比如计算总价,获得金额,统计等等。多个用户可以同时并反复的调用这个会话Bean的同一个实例。也就是共享同一个实例来完成业务逻辑。

而有状态会话Bean,需要保留用户的会话状态。换句话说在特定的条件下一个用户只对应一个有状态的会话Bean的实例。比如购物车,一个用户就必须对应一个有状态的会话Bean的实例,这个实例保存了这个用户所购买了的所有产品。而且每个用户都买的产品都不一样,所以他们不能共享实例。

再者就是二者的生命周期不同。

哪么如何才能编写一个SessionBean,哪么我们就要来学习一下SessionBena的编程模型。

SessionBean规范:
               |
               |___Home接口      用来和远程容器进行通信
               |
               |___远程接口        封装了Bean类的业务方法,暴露在外方便调用
               |
               |___Bean类          封装了具体的业务代码实现

ejb-jar.xml        (部署描述符)容器通过读取里面的配置信息,就知道哪些是会话Bean,哪些是实体Bena。还有他们的事务操作全部都定义在其中。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">

<ejb-jar>
     <display-name>EJBModule1</display-name>
     <enterprise-beans>
       <session>
         <ejb-name>Converter</ejb-name>
         <home>org.ejb.sessionbean.ConverterHome</home>
         <remote>org.ejb.sessionbean.Converter</remote>
         <ejb-class>org.ejb.sessionbean.ConverterBean</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>
       </session>
</ejb-jar>

weblogic-ejb-jar.xml      这个是我选择J2EE是weblogic后产生的,里面主要配置了ejb的Bean类名称和JNDI的名称。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE weblogic-ejb-jar PUBLIC "-//BEA Systems, Inc.//DTD WebLogic 8.1.0 EJB//EN" "http://www.bea.com/servers/wls810/dtd/weblogic-ejb-jar.dtd">

<weblogic-ejb-jar>
     <weblogic-enterprise-bean>
       <ejb-name>Converter</ejb-name>
       <jndi-name>Converter</jndi-name>
     </weblogic-enterprise-bean>
     <weblogic-enterprise-bean>
       <ejb-name>Count</ejb-name>
       <jndi-name>Count</jndi-name>
     </weblogic-enterprise-bean>
</weblogic-ejb-jar>

介绍完规范后,我们来讲解一下SessionBean被客户端的调用过程:

EJB学习之SessionBean(会话Bean)_第1张图片\

现在我们就来按照EJB规范来编写SessionBean,我们这个SessionBean的名称叫Count用于计算次数。

首先我们要编写的是Home接口,注意命名要规范。

CountHome:

Public interface CountHome extends EJBHome{

         //现在只是建立一个Home接口,它必须继承EJBHome

        public Count create () throws CreateException,RemoteException;
//该方法告诉容器需要获得一个去创建Bean类一个实例并返回它的引用(及远程接口)

}

------------------------------

其次是远程接口,我们命名为Count:

public interface Count extends EJBObect{

        //远程接口里面定义业务方法,它会抛出远程异常

        public int getNumber() throws RemoteException;

}

-------------------------------

最后我们编写Bean类,命名为CountBean:

public class CountBean implements SessionBean{

        SessionContext sessionContext;//上下文对象

        //注意我们编写的SessionBean必须实现SessionBean这个接口

        //这个接口里面定义了会话Bean的生命周期

        public void ejbCreate() throws CreateException {}//创建对象,可能抛出创建异常

         public void ejbRemove(){}//移出对象

         public void ejbActivate(){}//激活对象

         public void ejbPassivate(){}//钝化对象

         public void setSessionContext(SessionContext sessionCount){

           //在Bean类上设置上下文

           this.sessionContext = sessionCount;//系统会调用并传入上下文对象与Bean类中的上下文对象匹配

          }

          int count = 0;//声明一个成员变量

          //实际的业务代码实现

          public int getNumber(){

                System.out.println(count);

                count = count +1;

                return count;

          }

}

编写完这三个Java文件后,我们还需要编写ejb-jar.xml文件,配置整个部署信息。

<ejb-jar>
      <display-name>EJBModule1</display-name>
      <enterprise-beans>
        <session>
          <ejb-name>Count</ejb-name>
          <home>org.ejb.sessionbean.CountHome</home>
          <remote>org.ejb.sessionbean.Count</remote>
          <ejb-class>org.ejb.sessionbean.CountBean</ejb-class>
          <session-type>Stateless</session-type>
          <transaction-type>Container</transaction-type>
        </session>
</ejb-jar>

然后编辑weblogic-ejb-jar.xml将ejb组件的名称和jndi进行绑定

<weblogic-ejb-jar>
<weblogic-enterprise-bean>
        <ejb-name>Count</ejb-name>
        <jndi-name>Count</jndi-name>
      </weblogic-enterprise-bean>
</weblogic-ejb-jar>

 

使用JB编译后,生成一个*.ear文件。将这个文件部署到服务器上。如果没有异常则说明部署成功。

部署成功后,我们编写一个Client来测试EJB组件。

public class ConverterClient {

     public ConverterClient() {}

     public static void main(String[] args) {

         /*第一部分--------------------------------*/

         Properties properties = null;

         try {

             properties = new Properties();//配置文件

             //声明初始化工厂类

             properties.put(Context.INITIAL_CONTEXT_FACTORY,

                            "weblogic.jndi.WLInitialContextFactory");

             //指定服务器通信地址

             properties.put(Context.PROVIDER_URL, "t3://localhost:7001");

             //security_principal 安全_主要的(用户)

             properties.put(Context.SECURITY_PRINCIPAL, "");

             //security_credentials 安全_信任状(密码)

             properties.put(Context.SECURITY_CREDENTIALS, "");

         } catch (Exception e) {

             System.out.println("设置环境异常");

         }

         /*第二部分------------------------------*/

         ConverterHome home = null;

         if(properties!=null){

             try {

                 Context context = new InitialContext(properties);//初始化上下文

                 Object obj = context.lookup("Converter");//通过JNDI查找实例

                 try {//通过远程调用得到home对象(得到容器的骨架)

                     home = (ConverterHome) PortableRemoteObject.narrow(obj,

                             ConverterHome.class);

                 } catch (Exception ex1) {

                     System.out.println("得到远程引用异常");

                     ex1.printStackTrace(System.out);

                 }

             } catch (NamingException ex) {

                 System.out.println("上下文异常");

                 ex.printStackTrace(System.out);

             }

         }

 

         /*第三部分-----------------------------------------*/

         Converter converter= null;

         try {

             converter = home.create();//通过home骨架得到Converter存根(引用)

             converter.getHello("Hello world");

         } catch (RemoteException ex2) {

             ex2.printStackTrace(System.out);

         } catch (CreateException ex2) {

             ex2.printStackTrace(System.out);

         }

     }

有状态会话Bean,主要是保存的用户会话状态。一个有状态会话Bean实例对应一个用户。

那么我们首先来编写一个有状态的会话Bean。我们使用的开发工具为JBuilder2006,它开发EJB起来比较方便。EJB容器使用weblogic8.1中文版。

建立相应的EJB项目后,开打EJB Designer设计窗口。设计一个有状态会话Bean。

EJB学习之SessionBean(会话Bean)_第2张图片
在会话Bean上点击右键。设定相应参数。如图:
EJB学习之SessionBean(会话Bean)_第3张图片
Bean Name:指的是有状态会话Bean的名称。
Interfaces:表示它的调用接口的类型,remote表示远程。
Session type:表示会话Bean的类型,Stateful表示有状态。
Session synchronization:表示是否需要同步,false为不。
Transaction type:表示事务管理,Container表示EJB容器管理。
我们现在要写的一个例子是一个购物车的例子。我们介绍一下整个工程中所有的类:
EJB model:
            |___     ShopingCar.java                       有状态会话Bean的远程接口
            |
            |___     ShoppingCarBean.java             Bean类,代码实现类
            |
            |___     ShoppingCarHome.java             Home接口
Entity    :
            |___     Product.java                              产品类,表示实体。这个类必须实现 java.io.Serializable接口。
首先介绍Product的代码,非常简单。
/****************************************************************/
import java.io.Serializable;
public class Product implements Serializable {
      private String proName;//产品名称
      private double proPrice;//产品价格
      public Product() {
      }
      public Product(String proName,double proPirce){
          this.setProName(proName);
          this.setProPrice(proPrice);
      }

以下全是get和set方法......
/****************************************************************/
为什么这个实体类要实现序列化接口?应为EJB容器在初始化Bean的时候都有一个唯一的标识
这些获得唯一的标识的类都是必须实现Serializable的。当然还有其他用途就不一一介绍....
大家可以在上图看到,我在Bean当中添加了2个方法,一个是addList(Product product)另外一个是getList().相信大家看到这2个方面就该明白是干什么了。
以下是贴出相应Bean类的代码
/********************************************************/
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.CreateException;
import org.ejb.entity.Product;
import java.util.List;
import java.util.ArrayList;
public class ShoppingCarBean implements SessionBean {
      SessionContext sessionContext;
      List list;
      public void ejbCreate() throws CreateException {
      }
      public void ejbCreate(String name) throws CreateException {
          list = new ArrayList();//初始化产品集合
      }
      public void ejbRemove() {
      }
      public void ejbActivate() {
      }
      public void ejbPassivate() {
      }

      public void setSessionContext(SessionContext sessionContext) {
          this.sessionContext = sessionContext;
      }
      //添加某个产品到集合中
      public void addList(Product product) {
          list.add(product);
      }
    
      //得到所有产品
      public List getList() {
          return list;
      }
}
/**********************************************************/
当我在客户端远程调用EJB的时候,我就会使用到添加产品和得到所有产品的方法。
那么我们现在就来看看。在JSP页面里面如何调用:
<html>
    <head>
      <title>handlertest      </title>
    </head>
    <body bgcolor="#ffffff">
      <%
      try{
          Context    context = new InitialContext();//初始化上下文对象
         Object obj = context.lookup("ShoppingCar");//通过JNDI找到对象
         //得到骨架(通过远程调用,得到Home接口)
         ShoppingCarHome home = (ShoppingCarHome)PortableRemoteObject.narrow(obj,ShoppingCarHome.class);
         ShoppingCar shop = home.create("banseon");//通过Home接口,得到存根
         shop.addList(new Product("苹果",12.2));//添加产品
         shop.addList(new Product("香蕉",3.4));
         shop.addList(new Product("桔子",4.5));
         int i = shop.getList().size();
         out.println("现在产品总量为:"+i+"<br>");
         Handle d = shop.getHandle();
         session.setAttribute("Handle",d);
         shop = null;
         out.println("从新获取存根");
         shop = (ShoppingCar)((Handle)session.getAttribute("Handle")).getEJBObject();
         out.print(shop.getList().size());
         shop.remove();//删除服务器实例和本地存根。
      }catch(Exception e){
        e.printStackTrace();
      }
      %>
    </body>
</html>
其中最主要的是我们要保存客户端与服务器的通信的句柄。就是Handle
首先我们要得到,然后放入一个Session当中。Handle里面是2进制数据。
          Handle d = shop.getHandle();
         session.setAttribute("Handle",d);
当我们下回再与服务器通信的时候就可以取出,告诉服务器与我们客户端匹配的有状态会话Bean是哪一个了。
       shop = (ShoppingCar)((Handle)session.getAttribute("Handle")).getEJBObject();
     
基本上的用法就是这些。大家可以自由发挥。。。有空来这里提提问题吧。

你可能感兴趣的:(应用服务器,bean,weblogic,Security,ejb)