专稿:实战EJB之三 开发会话Bean(有状态会话Bean)

【EJB】会话Bean(Session Bean) 很多程序员,整天沉浸在业务代码的 CRUD 中,业务中没有大量数据做并发,缺少实战经验,对并发仅仅停留在了解,做不到精通,所以总是与大厂擦肩而过。我把私藏的这套并发体系的笔记和思维脑图分享出来,理论知识与项目实战的结合,我觉得只要你肯花时间用心学完这些,一定可以快速掌握并发编程。《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取! 阅读详情
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> Untitled Document

实战EJB系列

在以后的日子里,将由Jackliu向大家陆续提供一系列EJB教程,有学习EJB的朋友请同步参考EJB相关书籍,实战系列将以例程的方式帮助你理解这些基本的概念,其中将包括:

所有章节完毕后将制作成pdf电子文档,供大家下载。

实战EJB之三 开发会话Bean(有状态会话Bean)

会话Bean可以分为有状态会话Bean(stateful Bean)和无状态会话Bean(stateless Bean),有状态会话Bean可以在客户访问之间保存数据,而无状态会话Bean不会在客户访问之间保存数据。两者都实现了javax.ejb.SessionBean接口,EJB容器区通过部署文件ejb-jar.xml来判断是否为一个SessionBean提供保存状态的服务,另外,在程序实现上,无状态Bean不能声明实例变量,每个方法只能操作方法传来的参数,如果需要在引用期间维持一些数据状态,以在其他方法中可以引用,则可以把Bean设计成有状态会话Bean。在第二节中我们用一个SatatelessDate Bean例子描述了开发无状态会话Bean的过程及特性,下面的一节将介绍关于有状态会话Bean的一些特性和寿命周期,并用一个例子来证明这些特性。

在本节中你将了解到:

  • 什么是有状态Session Bean?
  • 有状态Session Bean寿命周期
  • 编写一个有状态Session Bean程序
  • 部署到应用服务器
  • 开发和部署测试程序
  • 运行测试程序
什么是有状态Session Bean?

有状态会话Bean(Stateful Session Bean)就是在客户引用期间维护Bean中的所有实例数据的状态值,这些数据在引用期间可以被其他方法所引用,其他客户不会共享同一个Session Bean的实例。Bean的状态被保存到临时存储体中,因为Bean是可以被序列化的,所以同样也可以把一个Bean状态保存到文件系统或数据库中。因为在调用方法时需要维护状态(这部分是有开销的),所以只有需要维护客户状态时才使用有状态会话Bean。典型的会话Bean是购物车,当一个客户第一次打开购物车时,系统为他分配一个购物车的会话Bean,在以后,每当客户选购了商品将改变购物车的商品记录,而这些记录数据将保存到用户会话数据中。

有状态Session Bean寿命周期

有状态Session Bean寿命周期由容器控制,Bean的客户并不实际拥有Bean的直接引用,当我们部署一个EJB时,容器会为这个Bean分配几个实例到组件池(component pooling)中,当客户请求一个Bean时,J2EE服务器将一个预先被实例化的Bean分配出去,在客户的一次会话里,可以只引用一次Bean,就可以执行这个Bean的多个方法。如果又有客户请求同样一个Bean,容器检查池中空闲的Bean(不在方法中或事务中,如果一个客户长时间引用一个Bean但执行一个方法后需要等待一段时间再执行另一个方法,则这段时间也是空闲的),如果全部的实例都已用完则会自动生成一个新的实例放到池中,并分配给请求者。当负载减少时,池会自动管理Bean实例的数量,将多余的实例从池中释放。

有状态会话Bean的寿命周期比无状态会话Bean更加的复杂,有状态会话Bean有四种状态:

  1. 不存在
  2. 方法现成
  3. 事务中方法现成
  4. 钝化

如图3-1所示:

<图3-1>

有状态会话Bean的初始化状态为不存在,当有客户引用一个Bean时,按照顺序调用newInstance()、setSessionContext()和ejbCreate()方法,与第一节中讲到的无状态调用顺序相同。当处于方法现成状态时,如果客户调用remove()方法,则回到不存在状态,并触发Bean的ejbRemove()方法。如果客户长时间不调用Bean或服务器准备释放一些内存资源,则容器将这些Bean从组件池中钝化,钝化过程容器将调用Bean的ejbPassivate()方法,使程序员有机会在钝化Bean时释放分配的资源。当一个客户请求一个被钝化的Bean时,容器可以激活Bean,激活过程容器将调用ejbActivate()放,使程序员有机会在Bean转到方法现成状态时分配Bean所需的资源。

Bean本身可以管理事务(BMT Bean-Managed Transactions),也可以由容器管理事务(CMT Container-Managed Transation)。对于CMT,容器在方法开始时打开事务,在方法结束时实现事务。Bean开发人员可以通过afterBegin()、beforeCompletion()、afterCompletion(Boolean)来获取事务的各个状态,如果afterCompletion(Boolean)中Boolean变量为true表示事务完成,为false表示事务被撤消。

编写一个有状态Session Bean程序

假设这次我们要为一个基金组织编写一个基金帐户的Bean组件,这个组件将为基金管理系统提供一个基金帐户的基本功能。为了能够描述清楚有状态会话Bean的特性,我们将之简化成提供三个业务逻辑接口:addFunds()方法为一个基金帐户添加基金,removeFunds()方法从基金帐户中取出基金,方法getBalance()为我们提供一个基金帐户的余额查询。我们为这个Bean起名为StatefulAccount

设计一个有状态的Session Bean至少包括四个步骤:

  1. 开发主接口
  2. 开发组件接口
  3. 开发Bean实现类
  4. 编写部署文件

注意:本节假设你使用的Windows操作系统。如果使用其他操作系统,可能影响到存储路径和JDK命令,但这与程序代码和部署文件内容无关。

1.开发主接口(StatefulAccountHome.java):

是由Bean开发人员编写的一个Bean的主接口(interface)程序,负责控制Bean的生命周期(生成、删除、查找Bean)。只需要开发人员给出一个主接口类,类方法的实现由容器来完成。

主接口扩展了javax.ejb.EJBHome接口,参考avax.ejb.EJBHome接口定义如下:


 package javax.ejb;

 import java.rmi.Remote;

 import java.rmi.RemoteException;

  

 public interface EJBHome extends Remote{

  public abstract EJBMetaData getEJBMetaData() throws RemoteException;

  public abstract HomeHandle getHomeHandle() throws RemoteException;

  public abstract void remove(Object obj) throws RemoteException,RemoveException;

  public abstract void remove(Handle handle) throws RemoteException,RemoveException;

 }

  • 方法getEJBMetaData()返回EJBMetaData接口的引用,取得Bean的信息,EJBMetaData不是远程接口。这个类扩展了java.io.Serializable,所以可序列化,具有序列化的特性
  • 方法getHomeHandle()返回主对象的句柄,句柄是主接口StatelessAccountHome的持久性引用,这个类扩展了java.io.Serializable,所以可序列化,具有序列化的特性,HomeHandle 对象可以传递给另一个JVM,且不传递安全信息,这样新的应用可以不使用JNDI来查找对象既可以获得这个主接口,并来创建和获得Bean实例。
  • 方法remove()用来删除一个Bean的实例,对于一个会话Bean,执行Remove操作将引用的Bean返回到池中,由池来管理其生命周期。

一般情况下,习惯将主接口的命名规则规定为<bean-name>Home,所以我们把这个主接口类起名为StatefulAccountHome

大部分逻辑方法已经被EJBHome定义,在我们要设计的远程主接口中,不必再重新定义。值得注意的是,我们需要为这个接口定义一个create()方法,用来获得一个实例Bean的引用,返回的对象类型是组件接口类StatefulAccount。与第二节的StatelessDateHome类定义基本相同,不同的是Create()方法需要一个double类型的fund参数,当客户创建一个Bean引用时,我们将通过这个参数初始化基金帐户的余额。Fund数值的状态将由容器来维护。

StatefulAccountHome.java代码:


import java.rmi.RemoteException;

import javax.ejb.CreateException;

import javax.ejb.EJBHome;



public interface StatefulAccountHome extends EJBHome{

 public StatefulAccount create(double fund) throws RemoteException,CreateException;

}

假设我们保存到D:/ejb/StatefulAccount/src/StatefulAccountHome .java

2.开发组件接口(StatefulAccount.java):

当远程用户调用主接口类生成方法(create(double))时,客户要得到一个组件的远程引用,因此EJB容器要求你为这个Bean的所有方法提供一个接口类,而类的实现则与远程主接口StatefulAccountHome 一样由容器在部署时自动生成。

组件接口扩展了avax.ejb.EJBObject接口,参考avax.ejb.EJBObject接口定义如下:


 package javax.ejb;

 import java.rmi.Remote;

 import java.rmi.RemoteException;

  

 public interface EJBObject extends Remote{

   public abstract EJBHome getEJBHome() throws RemoteException;

   public abstract Handle getHandle() throws RemoteException;

   public abstract Object getPrimaryKey() throws RemoteException;

   public abstract boolean isIdentical(EJBObject ejbobject) throws RemoteException;

   public abstract void remove() throws RemoteException,RemoveException;

 }

  • 方法getEJBHome()返回远程主接口对象的引用
  • 方法getHandle() 当前组件接口对象的句柄,和远程主接口的句柄HomeHandle一样,这个对象是被序列化的,所以可以保存到本地或通过RMI/IIOP协议传输给其他JVM上的客户使用,而免去JNDI查找和调用主接口的create方法,只要执行Handle.getEJBObject()方法即可取得这个Bean实例的引用。
  • getPrimaryKey()方法一般用于Entity Bean,如果在Session Bean中调用,抛出java.rmi.RemoteException。
  • 方法isIdentical()用于对当前引用的Bean实例和另一Bean实例进行比较,因为即便是Bean实例相同但有可能不是来自同一个引用,不能使用equals()方法。
  • 方法remove() 删除当前引用的Bean实例,由容器来决定是否真的释放气内存,通常会返换到组件池中。注意删除之后要将对象的引用指向为null。

一般情况下,习惯将组件接口的命名规则规定为<bean-name>,所以我们把这个组件接口类起名为StatefulAccount

大部分逻辑方法已经被EJBObject 定义,在我们要设计的组件接口StatefulAccount中,不必再重新定义,只要我们重申组件中有关业务逻辑的接口即可。为了使远程客户能够得到基金帐户的业务方法,我们必须对应Bean的实现类申明业务逻辑接口的方法。方法AddFunds(double)向一个帐户增加基金,removeFunds(double)方法从一个帐户中取出基金,getBalance()方法得到当前基金帐户的余额,注意这些类都被声名成接口方法,不需要我们在此实现。

在方法AddFunds和removeFunds中,如果参数不符合要求,抛出InsufficientFundException异常错误。

StatefulAccount.java代码:


import javax.ejb.EJBObject;

import java.rmi.RemoteException;



public interface StatefulAccount extends EJBObject{

 public void addFunds(double fund) 

     throws RemoteException,InsufficientFundException;

 public void removeFunds(double fund) 

     throws RemoteException,InsufficientFundException;

 public double getBalance()

     throws RemoteException;   

}

假设我们保存到D:/ejb/StatefulAccount/src/StatefulAccount .java

InsufficientFundException.java代码:




public class InsufficientFundException extends java.lang.Exception{

        public InsufficientFundException(){super();}

        public InsufficientFundException(String msg){super(msg);}

}

假设我们保存到D:/ejb/StatefulAccount/src/InsufficientFundException .java

3.开发Bean实现类(StatefulAccountEJB.java):

这个类包含了业务逻辑的所有详细设计细节。会话Bean的实现类实现了(implements)javax.ejb.SessionBean所定义的接口,首先我们先熟悉一下SessionBean的定义:


package javax.ejb;

impot java.rmi.RemoteException;



public interface SessionBean extends EnterpriseBean{

  public void setSessionContext(SessionContext ctx) throws EJBException,RemoteException;

public void ejbRemove() throws EJBException,RemoteException;

public void ejbActivae()throws EJBException,RemoteException;

public void ejbPassivate()throws EJBException,RemoteException;

}

容器通过这些方法将相关信息通知给Bean实例,所有的方法都抛出RemoveException方法是为了与1.0规范兼容,之后版本编写的Bean只需要抛出EJBException即可。

setSessionContext()方法将会话的语境放到对象变量中,容器在结束会话Bean或自动超时死亡之前将会自动调用ejbRemove()方法,所以在此可以填入用来释放某些资源的代码。当实例被钝化或被激活时,调用ejbActivae()和ejbPassivate()方法。在钝化过程之前,容器调用ejbPassivate()方法,Bean的开发人员可以在这个方法里释放占用的资源,待Bean被激活时,在ejbPassivate()方法中再分配这些资源。

一般情况下,习惯将组件实现类的命名规则规定为<bean-name>EJB,所以我们把这个组件类起名为StatefulAccountEJB

类StatefulAccountEJB声明要实现SessionBean的定义,所以,我们必须完全实现SessionBean的接口定义。

StatefulAccountEJB.java代码:


import javax.ejb.*;



public class StatefulAccountEJB implements SessionBean{

 public void ejbCreate(double fund)throws CreateException{

    if (fund<0)

       throw new CreateException("Invalid fund");

    this.fundBalance=fund;

 }

 

 public void ejbRemove(){}

 public void ejbActivate(){}

 public void ejbPassivate(){}

 public void setSessionContext(SessionContext ctx){} 

 

 //实例变量,有状态的会话bean将在组件池中维护这个实例的值

 private double fundBalance;

 

 //向基金帐户增加基金

 public void addFunds(double fund)throws InsufficientFundException{

    if (fund<0)

       throw new InsufficientFundException("Invalid fund");

    this.fundBalance =fund;  

 }

 

 //从基金帐户撤除部分基金

 public void removeFunds(double fund)throws InsufficientFundException{

   if(fund<0)

      throw new InsufficientFundException("Invalid fund");

   if(this.fundBalance<fund)

      throw new InsufficientFundException("the balance less than fund");

   this.fundBalance-=fund;

 }



 //得到基金帐户的余额

 public double getBalance(){

   return this.fundBalance;

 } 

}

假设我们保存到D:/ejb/StatefulAccount/src/StatefulAccountEJB .java

到此为止我们的Bean程序组件已经编写完毕了,使用如下命令进行编译:


cd bean/StatefulAccount

mkdir classes

cd src

javac -classpath %CLASSPATH%;../classes -d ../classes  InsufficientFundException.java 
StatefulAccount.java StatefulAccountHome.java StatefulAccountEJB.java

如果顺利你将可以在../StatefulAccount/classes目录下发现有四个类文件。

4.编写部署文件:

一个完整的ejb是由java类和一个描述其特性的ejb-jar.xml文件组成,部署工具将根据这些文件部署到容器中,并自动生成容器所需的残根类。

按照下面个格式编写一个ejb-jar.xml文件,对于DTD介绍此处省去。

ejb-jar.xml文件:


<?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>

    <description>    

        This is StatefulAccount EJB example

    </description>

    <display-name>StatefulAccountBean</display-name>

    <enterprise-beans>

        <session>

            <display-name>StatefulAccount</display-name>

            <ejb-name>StatefulAccount</ejb-name>

            <home>StatefulAccountHome</home>

            <remote>StatefulAccount</remote>

            <ejb-class>StatefulAccountEJB</ejb-class>

            <session-type>Stateful</session-type>

            <transaction-type>Container</transaction-type>

        </session>

    </enterprise-beans>

</ejb-jar>

假设我们保存到D:/ejb/StatefulAccount/classes/META-INF/ejb-jar.xml(注意META-INF必须大写)

现在让我们看看当前的目录结构:




StatefulAccount 
       <文件夹>
        

   classes
        <文件夹>
         

     META-INF
         <文件夹>  
         
        
       

         ejb-jar.xml

     InsufficienFundException.class

     StatefulAccount .class

     StatefulAccount EJB.class

     StatefulAccount Home.class

   src
       <文件夹>

     InsufficientFundException.java

     StatefulAccount.java

     StatefulAccountEJB.java

     StatefulAccountHome.java



部署到应用服务器

在部署之前我们需要将这些类文件和xml文件做成一个jar文件,EJB JAR文件代表一个可被部署的JAR库,在这个库里,包含了服务器代码与EJB模块的配置。ejb-jar.xml文件被放置在JAR文件所指定的META-INF目录中。我们可以使用如下命令得到EJB JAR文件:


cd d:/ejb/StatefulAccount/classes    (要保证类文件在这个目录下,且有一个META-INF子目录存放ejb-jar.xml文件)

jar -cvf  StatefulAccount.jar *.*

确保StatefulAccount.jar文件包括的文件目录格式如下:


META-INF
      <文件夹>

   ejb-jar.xml

InsufficientFundException.class

StatefulAccount.class

StatefulAccountEJB.class

StatefulAccountHome.class

部署工具一般由Java应用服务器的制造商提供,在这里我使用了Apusic应用服务器,并讲解如何在Apusic应用服务器部署这个StatefulAccount组件。

注意,如果使用其他部署工具,原理是一样的。要使用Apusic应用服务器,可以到www.apusic.com上下载试用版。

确定你的Apusic服务器已经被启动。 打开"部署工具"应用程序,点击文件->新键工程:

第一步:选择"新建包含一个 EJB组件打包后的EJB-jar模块"选项

第二步:选择一个刚才我们生成的StatefulAccount.jar文件

第三步:输入一个工程名,可以随意,这里我们输入StatefulAccount

第四步:输入工程存放的地址,这里我们假设被存放到D:/ejb/StatefulAccount/deploy目录下

完成四个步骤后,如果没有问题将出现StatefulAccountBean的部署界面,基本的参数配置已经在我们刚才编写的ejb-jar.xml中定义,可以点击部署->部署到Apusic应用服务器完成部署工作。

开发和部署测试程序

SessionBean组件是没有任何运行界面的,组件的实例被容器所管理,所以我们要测试这个Bean组件,需要写一段测试程序,这里,我们写一段小服务程序(Java Servlet)。

关于如何编写Servlet我们这里不做介绍。InitialContext 对象用来获取当前servlet小应用程序的语境,方法lookup从组件池中查找一个JNDI对象,并取得一个远程主接口的引用。java:comp/env/ejb/StatefulAccount是我们刚才部署StatefulAccount组件的JNDI名,请参考ejb-jar.xml中的 项。要注意的是,lookup()方法返回的是一个Object类型的远程主接口对象的残根,为此需要使用javax.rmi.PortableRemoteObject的narrow()方法来获取一个具体的对象引用,narrow()方法:第一个参数是lookup()方法返回的对象,第二个参数是要得到的引用类型。我们通过narrow()方法并经过造型得到了一个StatefulAccountHome对象的实例引用,调用create()方法获取一个StatefulAccount组件接口的实例引用,然后就可以与本地一样去引用这个实例。使用完毕后不要忘记将实例的引用指向一个Null。 在create方法中,我们为基金帐户初始化一个数值,通过引用,把这个值传递给StatefulAccountEJB中定义的fundBalanced对象,注意这个对象的状态由容器维护。通过addFund、removeFund和getBalance方法我们可以测试fundBalanced状态改变所带来的影响。

下面是提供的代码:

StatefulAccountServlet.java文件:


import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

import javax.ejb.*;

import javax.naming.InitialContext;



public class StatefulAccountServlet extends HttpServlet{

 public void service(HttpServletRequest req,HttpServletResponse res) throws IOException {

   res.setContentType("text/html");        

   PrintWriter out =res.getWriter();

   out.println("<html><head><title>StatefulAccountServlet</title></head>");

   out.println("<body><h2>Test Result:<hr>");                

     try{

        InitialContext ctx =new InitialContext();

        Object objRef =ctx.lookup("java:comp/env/ejb/StatefulAccount");

        StatefulAccountHome home=(StatefulAccountHome)

          javax.rmi.PortableRemoteObject.narrow(

          objRef,StatefulAccountHome.class);

        

        //得到一个基金帐户对象的引用,并初始化帐户金额为100000                    

        StatefulAccount bean=home.create(100000);

        out.println("the account balance:" bean.getBalance() "<br>");

        //向基金帐户增加5000.25

        bean.addFunds(5000.25);

        out.println("method of addFunds(5000.25) Result:" bean.getBalance() "<br>");

        //从基金帐户调出1000.02

        bean.removeFunds(1000.02);

        out.println("method of removeFunds(1000.02) Result:" bean.getBalance());

        out.println("<hr>");

        out.println("current account balance:" bean.getBalance());

        

        bean=null;

        

     }catch(javax.naming.NamingException ne){

        out.println("Naming Exception caught:" ne);

        ne.printStackTrace(out);

     }catch(javax.ejb.CreateException ce){

        out.println("Create Exception caught:" ce);

        ce.printStackTrace(out);

     }catch(java.rmi.RemoteException re){

        out.println("Remote Exception caught:" re);

        re.printStackTrace(out);

     }catch(InsufficientFundException ie){

        out.println("InsufficientFund Exception caught:" ie);

        ie.printStackTrace(out);

     }

     out.println("</body></html>");       

 }               

}

假设我们将文件保存到D:/ejb/StatefulAccount/src/StatefulAccountServlet.java

使用如下命令编译Servlet


cd D:/ejb/StatefulAccount

mkdir test

cd test

mkdir WEB-INF

cd WEB-INF

mkdir classes

cd D:/ejb/StatefulAccount/src

javac -classpath %CLASSPATH%;../classes/ -d ../test/WEB-INF/classes StatefulAccountServlet.java



编译成功后将这个servlet部署到与StatefulAccount同一工程中,在部署前需要我们为部署编写一个web.xml,并制作Web模块文件(war文件),其中告诉部署工具这个servlet需要参考的一些资源和部署信息,这里我们将定义一个JNDI参考:


  <ejb-ref>

    <description></description>

    <ejb-ref-name>ejb/StatefulAccount</ejb-ref-name>

    <ejb-ref-type>Session</ejb-ref-type>

    <home>StatefulAccountHome</home>

    <remote>StatefulAccount</remote>

    <ejb-link>StatefulAccount</ejb-link>

  </ejb-ref>

<ejb-ref-name>告诉部署工具,这个Web模块需要参考的资源JNDI名称, 被指定参考一个SessionBean组件。 web.xml文件内容如下:




<?xml version="1.0" encoding="UTF-8"?>



<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>



<web-app>

  <icon>

    <small-icon></small-icon>

    <large-icon></large-icon>

  </icon>

  <display-name>StatefulAccount</display-name>

  <description></description>

  <context-param>

    <param-name>jsp.nocompile</param-name>

    <param-value>false</param-value>

  </context-param>

  <context-param>

    <param-name>jsp.usePackages</param-name>

    <param-value>true</param-value>

    <description></description>

  </context-param>

  <ejb-ref>

    <description></description>

    <ejb-ref-name>ejb/StatefulAccount</ejb-ref-name>

    <ejb-ref-type>Session</ejb-ref-type>

    <home>StatefulAccountHome</home>

    <remote>StatefulAccount</remote>

    <ejb-link>StatefulAccount</ejb-link>

  </ejb-ref>

</web-app>

假设我们将文件保存到D:/ejb/StatefulAccount/test/WEB-INF/web.xml

下面我们要部署这个Servlet到J2EE服务器。J2EE Web应用可以包括Java Servlet类、JavaServer Page组件、辅助的Java类、HTML文件、媒体文件等,这些文件被集中在一个War文件中。其中War结构具有固定的格式,根目录名为WEB-INF,同一目录下应该有一个web.xml文件,用来描述被部署文件的部署信息,Jsp、html等文件可以放置在这个目录下,同时WEB-INF目录下可能存在一个classes目录用于存放Servlet程序,如果引用了一些外部资源,则可以被放置到WEB-INF/lib目录下。使用下面的命令生成这个Servlet测试程序的war文件:


cd D:/ejb/StatefulAccount/test/

jar -cvf statefulAccount.war *.*



确保statefulAccount.war文件包括的文件目录格式如下:


WEB-INF
      <文件夹>
       

  classes
       <文件夹>
      

    StatefulAccountServlet.class

  web.xml

成功编译后,将这个servlet一同部署到statefulAccount工程中,我们回到"部署工具",点击编辑-->填加一个Web模块,选择我们刚刚编译成的statefulAccount.war文件 点击部署->部署到Apusic应用服务器完成部署工作。

运行测试程序

打开浏览器,在浏览器中输入:


http://localhost:6888/statefulAccount/servlet/StatefulAccountServlet

localhost-Web Server的主机地址

:6888-应用服务器端口,根据不同的应用服务器,端口号可能不同

/statelessfulAccount-部署servlet时指定的WWW根路径值

/servlet-ejb容器执行servlet的路径

/StatefulAccountServlet-测试程序

如果运行正常应该能够看到下面的结果

<图3-2>

EJB学习笔记——会话Bean 1.EJB3简介:EJB是企业级java bean(Enterprise Java Bean)开发技术,是基于IIOP协议的分布式远程方法调用技术(RMI),EJB3在JavaEE5中被正式引入,去掉了EJB2以前的复制度,使得EJB3更加轻量级,同时将实体Bean单独分拆成为JPA规范,从而使EJB3更加专注于会话Bean和消息驱动Bean的业务逻辑,同时EJB3中全面支持java注解方式,大大简化开发的难度提高开发效率。2.在客户端调用一个简单EJB3程序:首先使用一个简单例子演示客户端调用EJB3的基 阅读详情

相关推荐

EJB——会话bean(二)

为什么使用会话bean 1.并发和线程安全        构造服务器端应用程序的重点在于可以是客户端同时共享,会话bean用于处理客户端请求,他们支持高并发。容器利用很多技术“自动”确保你不必担心并发和线程安全方面的问题。 2.远程处理Web服务        会话bean支持基于Java远程方法调用的本地访问和基于简单对象访问协议(Simp

徐凤竹 程序人生 1568

如何开发会话Bean(有状态会话Bean)

<br /> <br /> 会话Bean可以分为有状态会话Bean(stateful Bean)和无状态会话Bean(stateless Bean),有状态会话Bean可以在客户访问之间保存数据,而无状态会话Bean不会在客户访问之间保存数据。两者都实现了javax.ejb.sessionBean接口,EJB容器区通过部署文件ejb-jar.xml来判定是否为一个SessionBean提供保存状态的服务,另外,在程序实现上,无状态Bean不能声明实例变量,每个方法只能操作方法传来的参数,假如需要在引用期间维

hooabc的专栏 529

Java EE中有状态与无状态会话Bean详解与实战

通过对无状态和有状态会话Bean在功能适用性、生命周期管理、资源消耗、并发性与可扩展性等方面的深入比较,可以看出:无状态Bean更适合构建通用服务、微服务、REST接口等无需维护状态的场景,具备高并发、易扩展、低资源消耗等优势。有状态Bean更适合需要维护客户端会话状态的业务场景,如购物车、用户会话管理等,但其资源占用高、扩展性受限,尤其在分布式环境下面临更多挑战。

weixin_28999139的博客 864

Java 面试 宝典 (2)

   JAVA华为面试题JAVA方面1 面向对象的特征有哪些方面   2 String是最基本的数据类型吗? 3 int 和 Integer 有什么区别4 String 和StringBuffer的区别5运行时异常与一般异常有何异同?异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求

700

代码详解——Transformer

对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。当 Decoder 的输入矩阵和 Mask 矩阵输入矩阵包含 “ I have a cat” (0, 1, 2, 3, 4) 五个单词的表示向量,Mask 是一个 5×5 的矩阵。然后判断是否传入的mask, 如果有mask (mask参数值不为None),则把mask为0的位置,将对应位置的attn的值设为无穷小的负数。可以发现得到的输出和输入的K,Q,V的大小相同。

zyw2002的博客 7214

Windows10下RTABMAP+T265实现三维建图

win10+rtabmap+t265扫描地形

Suxiang1997的博客 3486

Spring 中Bean 的this 调用

前言 在我们使用Spring时,可能有前辈教导过我们,在bean中不要使用this来调用被@Async、@Transactional、@Cacheable等注解标注的方法,this下注解是不生效的。 那么大家可曾想过以下问题 为何致this调用的方法,注解会不生效 这些注解生效的原理又是什么 如果确实需要调用本类方法,且还需要注解生效,该怎么做? 代理是否可以做到this调用注解就直接生效? 通过本文,上面的疑问都可以解决,而且可以学到很多相关原理知识,信息量较大,那么就开始吧 现象 以@A

jelin1230的专栏 1395

IPD的分析工具与模型(十六)CBB公用基础模块管理实现资源共享,缩短开发周期降低成本

CBB流程的开发环节,基于CBB规划中所识别和设计的CBB,进行CBB的详细设计(包括参数设计和接口设计),并最终实现CBB的落地开发。作为特殊类型的技术构件,CBB的开发流程,可沿用技术开发中的构件开发流程,具体包括概念、计划、开发和迁移等步骤,具体可参见前文的相关介绍。有了蓝图与架构设计,落地实施是关键攻坚。具体工作内容包括:具体工作内容包括:a. 以相似性、聚类、相对独行性、可组合、可扩展性、可维护性等原则为指导,按照产品的功能特征和业务类型,聚焦零散的功能点,形成功能模块,实现产品功能模块的划分;

Easyways1的博客 1378

EJB2.0有状态SessionBean

环境: JBoss 4.0.2 JDK1.5 IDEA8.1.4 一、EJB开发 packagelavasoft.testejb20yzt;importjavax.ejb.SessionBean;importjavax.ejb.SessionContext;/** * Bean类 * 所有具体的业务逻辑都在此类里面,此...

weixin_34072458的博客 165

从入门到精通:用友BIP旗舰版全模块实施与运维实战指南

本文详细介绍了用友BIP旗舰版的全模块实施与运维实战指南,涵盖财务云、供应链云、生产制造等核心模块的配置与优化技巧。通过渐进式学习法和实战案例,帮助用户从入门到精通,提升系统实施效率和运维能力,特别适合企业IT人员和实施顾问参考。

weixin_29207533的博客 899

复现报告:《多回路人机控制系统仿真及II型PIO分析》方法复现与代码实现

本文复现了谭文倩硕士论文《多回路人机控制系统仿真及II型PIO分析》中的关键方法,重点实现了频域驾驶员模型辨识和参数灵敏度分析。通过数字化提取论文图表数据,构建了结构驾驶员模型传递函数,并验证了参数变化对系统特性的影响。采用MATLAB实现了描述函数计算、模型参数辨识和灵敏度分析算法,为后续神经网络模型辨识和II型PIO研究奠定了基础。由于缺乏原始实验数据,部分结果通过数值模拟获得,但仍有效重现了论文的核心分析方法。~~~~~

huanghm88的专栏 175

有状态会话Bean实例

K:/test23/ejb/src/StatefulHome.javapackage ejbs;public interface StatefulHome extends javax.ejb.EJBHome {   public Stateful create(String str) throws java.rmi.RemoteException, javax.ejb.CreateExceptio

Jim Yang 1386

SAP-ABAP:SAP创建CDS视图(SQL语句创建)实例详解

通过Eclipse和ADT创建CDS视图是SAP开发中的一项重要技能。CDS视图不仅简化了数据建模,还提供了高性能和灵活性。掌握CDS视图的开发和使用,可以帮助你更好地支持SAP S/4HANA和Fiori应用的开发。

baidu_35680696的博客 1824

EJB——有状态的会话bean和无状态的会话bean

前面文章介绍过EJB的一些基本概念和三种bean,今天重点介绍一下会话bean中的有状态会话bean和无状态会话bean。  会话bean分为有状态的会话bean和无状态的会话bean:有状态会话bean :  每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bea

邵鸿鑫 7654

嵌入式软考必备知识点:嵌入式系统开发中的重要概念和示例代码

在嵌入式软考中,有一些重要的知识点需要掌握,包括嵌入式系统的基本概念、编程语言、实时操作系统和硬件接口等。实时操作系统是一种专门设计用于嵌入式系统的操作系统,可以提供对任务调度、中断处理和资源管理等方面的支持。GPIO(通用输入输出):GPIO是嵌入式系统中常用的硬件接口,用于连接外部设备和嵌入式系统。以上是嵌入式软考中的一些必备知识点,包括嵌入式系统的基本概念、编程语言、实时操作系统和硬件接口。通过配置串口的波特率、数据位数和校验位等参数,可以实现与其他设备的可靠通信。一、嵌入式系统的基本概念。

PixeGO的博客 313

YOLO11涨点优化:Loss魔改 | WIoU (Wise-IoU) v3版本全面替换,基于动态非单调聚焦机制,让模型更聪明地学习

YOLOv11目标检测中的WIoU v3损失函数改进 本文探讨了YOLOv11目标检测模型中CIoU损失函数的局限性,并提出了WIoU v3改进方案。关键发现包括: CIoU的缺陷:在低质量样本(小目标/遮挡目标)上过度惩罚,导致模型优化方向偏离,小目标AP往往比大目标低30%左右。 WIoU v3的创新: 动态非单调聚焦机制:根据样本"离群度"智能分配梯度 让模型重点优化中等质量样本,减少对低质量样本的无效关注 采用指数移动平均来自适应调整质量评判标准 实际效果:WIoU v3在保持大

2601_95807009的博客 422

EJB有状态的会话Bean和无状态的会话Bean的区别

在EJB里面,会话Bean分为两种,一种是有状态的会话Bean,另一种是无状态的会话Bean,本节主要讲解一下两者之间的区别。        对于有状态的会话Bean,这种情况属于,服务端与你单独开辟了一块空间与你进行交互。而客户端感觉服务端单独为他自己服务似的。而无状态的会话Bean,则服务端不提供了一个资源但是谁用都行,他不负责。所以客户端在使用的时候,则会感到这个服务 与其他人共享似的。服务

赵崇 2530

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

什么时候使用有状态会话bean

首先你应该清楚Session bean在服务器上是怎么样被创建以及管理的。拿无状态会话bean来说服务器在实例池中维护了它的很多实例。每次客户端请求的时候任意一个无状态的会话bean都可能会被选择出来,来对这个请求作出相应的处理。也就是说如果客户端发起两次请求那么很有可能会是两个不同的无状态会话bean实例来做处理。实际上在这两个无状态会话bean之间没有什么联系。同样的如果客户端消失那么无状态会

郗晓勇|利己者生,利人者恒 3134

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

EJB3.0开发有状态会话bean

 EJB3.0开发有状态的会话bean,步骤与无状态会话bean类似,只需要在无状态会话bean中把@Stateless改成@Statefulejb类代码如下package wang.ejb3.impl;import javax.ejb.EJB;import javax.ejb.Remote;import javax.ejb.Local;import javax.ejb

天空的云 1323

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

EJB系列(三)--有状态会话Bean和无状态会话Bean

EJB的基本分类     EJB分为EnterpriseBean(企业Bean)和Persistence(持久化),持久化Bean指的是Entity Bean(实体Bean,是一个代表存在于数据库中业务对象的复杂业务实体)。企业Bean又包括Session Bean(会话Bean,完成一个清晰的解耦的任务)和Message Driven Bean(MDB,消息驱动Bean,基于JMS,专门用于异

帆布鞋也能走猫步 1378

有状态会话bean

在会话bean综述中,描述了无状态和有状态bean的区别在于客户端和服务器之间交互形式不同。对于无状态会话bean,交互的开始和结束都在同一个方法中。有时客户端需要发出多个服务请求(需要调用多个方法),而每个请求需要访问或者考虑前面的请求结果。有状态会话bean的出现就是为了处理这种情况,通过向客户端提供一个专用的服务(某一个可以保留前面状态的bean),当客户端获得bean的引用时启动该服务,并

郗晓勇|利己者生,利人者恒 3720

EJB 有状态会话bean无状态会话bean详解

下面主要对Session  Bean讨论     现实中,很多朋友对两种session bean存在误解,认为有状态是实例一直存在,保存每次调用后的状态,并对下一次调用起作用,而认为无状态是每次调用实例化一次,不保留用户信息。仔细分析并用实践检验后,你会发现,事实恰好相反:有状态和无状态会话bean的本质区别是它们的生命期。    首先解释一个下面要用到的概念--用户:session be

eddle的专栏 1265

Java - 有状态bean和无状态bean

有状态Bean和无状态Bean的本质区别:声明周期 1. 前言:EJB EJB:称为企业Java beans,是基于分布式事务处理的企业级应用程序的组件。 Sun公司发布的文档中对EJB的定义是:EJB是用于开发和部署多层结构的、分布式的、面向对象的Java应用系统的跨平台的构件体系结构 EJB种类: EJB容器可以接收三类EJB: 会话Bean(Session Beans) 有状态会话Bean 无状态会话Bean 实体Bean(Entity Bean) 消息驱动Bean(Message Dri.

qq_40286155的博客 2484

详解EJB 3会话Bean

 详解EJB 3会话Bean           在本文中,将讨论EJB 3会话Beans——EJB客户端应用程序所用到的核心业务服务对象,有助于理解简单新颖的EJB 3会话Bean模型,主要涉及以下主题: Ø 会话Bean类型,包括有状态及无状态,及何时该用何种。Ø Bean类、业务接口、业务方法。Ø 通过会话Bean注释符实现的依赖性注入(即资源捆绑)。Ø 

谢启东的专栏 1875

EJB基础一 无状态会话BEAN使用

EJB基础一 无状态会话BEAN使用 EJB是J2EE的一条标准。以往EJB被人诟病,缺点是复杂,沉重。然后spring崛起了,spring因其轻量级,开发方便而得到了迅速地推广。但是这是过去了,EJB 2.X确实存在这个特点。但新标准的EJB 3.X却在向轻量级转变,而且开发效率可以说完全与spring相当。 要进行EJB开发,必须有EJB容器,tomcat是默认没有实现EJB的。实现了EJ

ilovewqf的博客 1767
上一篇: 专稿:实战EJB之二 开发会话Bean(无状态会话Bean)
下一篇: 用连接池提高Servlet访问数据库的效率
java169
博客等级 码龄18年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值