`

会话 Bean(Session Bean)

    博客分类:
  • EJB
阅读更多
Session Bean 是实现业务逻辑的地方。简单地说,像我们要实现两数相加或是从数据库中读取数据,都是通过Session Bean 来实现。根据是否可以维护会话状态,Session Bean 分为有状态 bean 和无状态 bean。有状态 bean 可以维护会话状态,无状态 bean 不维护会话状态。要维护会话状态,意味着 EJB 容器要为每个用户创建一个 bean实例,并通过该实例保存着与用户的会话状态。不维护会话状态,意味着一个 bean 实例不需要保存与某个用户的会话状态,这时一个 bean 实例可以为多个用户服务。

要开发一个 Session Bean,  我们需要定义接口和 Bean class。其中接口分为远程(remote)和本地(local)接口。EJB3.0在中,不要求你同时实现 remote 和 local 接口,但实现两者是比较好的做法。
 远程接口(remote interface):定义了 session bean 的业务方法,这些方法可以被来自 EJB 容器之外的应用访问到。
 本地接口(local interface):同样定义了 session bean 的业务方法,这些方法可以被同处于 EJB 容器内的其它应用使用。因为 local 接口允许 bean 之间直接通过内存交互,没有分布式对象协议的开销,从而改善了性能。
 Bean 类(bean class):bean class 包含了业务逻辑,它必须具备一个远程或本地接口。在 Bean 类,我们应该实现接口的业务方法,尽管这并不是必须的,但我们没理由不这样做。

1 Stateless Session Beans(无状态 bean)开发

由于无状态会话 Bean 不维护会话状态,意味着一个 bean 实例可以为多个用户服务。因此 EJB 容器使用实例池化技术管理无状态会话 Bean。简单的说就是:当无状态会话 Bean 部署到应用服务器时,EJB 容器会为它预先创建一些 bean 实例放在对象池。当有用户访问 EJB 方法时,EJB 容器会从对象池中取出一个实例为之服务,服务完了就回到对象池。当下一个用户再访问 EJB 方法时,EJB 容器有可能再次把该实例取出来为之服务。正因如此,无状态会话 Bean 只需要少量的实例就可以为成百上千的用户服务,大大提高了系统性能。

由于无状态会话 Bean 能够支持多个用户,并且通常在 EJB 容器中共享,可以为需要大量客户的应用提供更好的扩充能力。无状态会话 Bean 比有状态会话 Bean 更具性能优势,在条件允许的情况下开发人员应该首先考虑使用无状态会话 Bean。

1.1开发只实现 Remote 接口的无状态 Session Bean
在开发前,先熟悉一下本例子的调用流程图:

1. 浏览器请求 Test.jsp 文件
2. 应用服务器的 JSP 引掣编绎 Test.jsp
3. Test.jsp 通过 JNDI 查找获得 HelloWorld EJB 的存根对象,然后调用 SayHello()方法,EJB 容器截获到方法调用。
4. EJB 容器调用 HelloWorld 实例的 SayHello()方法.

现在我们就开始本例子的开发。首先在 Eclipse 中新建一个普通的 java 项目,然后把[Jboss 安装目录]/client 下的所有 jar 文件加入到项目的构建路径中。如果不需要在项目中使用单元测试用例或普通 J2SE 调用 EJB,你只需要加入 javaee.jar,该文件在本书源代码 lib/javaee 目录下。接下来开始代码编写。

开发步骤如下:
第一步:定义一个包含业务方法的接口。这个接口不需要包含任何注释,它是一个普通的 java 接口。调用 EJB的客户端使用这个接口引用从 EJB 容器返回的存根(stub)。代码如下:HelloWorld.java
package com.foshanshop.ejb3;
public interface HelloWorld {
    public String SayHello(String name);
}

第二步:编写 Bean class。
HelloWorldBean.java 。Bean 类推荐的命名方式是:接口+Bean ,如: HelloWorldBean 。
package com.foshanshop.ejb3.impl;
import com.foshanshop.ejb3.HelloWorld;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless
@Remote ({HelloWorld.class})
public class HelloWorldBean implements HelloWorld {


    public String SayHello(String name) {
        return name +"说:你好!世界,这是我的第一个EJB3哦.";
    }
}

在 Bean 类上面有两个注释@Stateless 和@Remote,@Stateless 注释指明这是一个无状态会话 Bean。@Stateless 注释的定义如下:
Package javax.ejb;
@Target(TYPE) @Retention(RUNTIME)
public @interface Stateless {
   String name( ) default "";
   String mappedName() default "";
}

name()属性用于指定 session bean 的 EJB 名称。该名称在 EJB Jar 包中必须是全局唯一的,而在 EAR 中却可以重复(因为 EAR 可以包含多个 EJB Jar,而每个 jar 可以存在一个同名的 EJB,在 EAR 中要定位某个 EJB,可以这样使用:xxx.jar#HelloWorldBean)。如果不指定该属性,默认就是 bean class 的非限定名称。对本例而言,EJB 名称默认为 HelloWorldBean。
mappedName()属性指定 Bean 的全局 JNDI 名称,这个属性在 weblogic,Sun 应用服务器和 glassfish 起作用。

@Remote 注释指定这个无状态 Bean 的 remote 接口。Bean 类可以具有多个 remote 接口,每个接口之间用逗号分隔,如:@Remote ({HelloWorld.class,Hello.class,World.class})。如果你只有一个接口,你可以省略大括号,对于本例而言,可以写成这样:@Remote (HelloWorld.class)。

经过上面两步,一个HelloWorld EJB就开发完了。现在我们把它发布到Jboss中。在发布前我们需要把它打成Jar包。JAR包的方法有很多,打如使用 jar 命令、集成开发工具或者Ant。下面为你介绍两种常用的打包方式:Eclipse打包向导和 Ant 打包。

Eclipse 打包向导
在 Eclipse 开发环境下,可以通过导出向导进行打包。在项目名称上点击右键,在跳出的菜单中选择“Export(导出),在“Export”对话框选择“JAR file”点“Next”,在“select the resources to export(选择要导出的资源)”一栏,展开你的项目并选择需要打包的文件。然后选择一个存放目录及文件名。点“Finish”结束打包。

Ant 打包任务
使用 Ant 打包是比较方便的,也是作者推荐的打包方式。我们可以在项目根目录下建立一个名为 build.xml 的 xml文件,然后在 xml 文件里面定义我们的打包任务。如下:
<?xml version="1.0"?>
<project name="HelloWorld" default="ejbjar" basedir=".">
   <property environment="env" />
   <property name="src.dir" value="${basedir}/src" />
   <property name="jboss.home" value="${env.JBOSS_HOME}" />
   <property name="build.dir" value="${basedir}/build" />
   <property name="build.classes.dir" value="${build.dir}/classes" />


   <!-- Build classpath -->
   <path id="build.classpath">
       <fileset dir="${jboss.home}/client">
              <include name="*.jar" />
        </fileset>
        <pathelement location="${build.classes.dir}" />
    </path>
    <target name="prepare" depends="clean">
        <mkdir dir="${build.dir}" />
        <mkdir dir="${build.classes.dir}" />
    </target>
    <target name="compile" depends="prepare" description="编绎">
        <javac srcdir="${src.dir}" destdir="${build.classes.dir}" debug="on"
deprecation="on" optimize="off" includes="**">
              <classpath refid="build.classpath" />
        </javac>
    </target>
    <target name="ejbjar" depends="compile" description="创建EJB发布包">
        <jar jarfile="${basedir}/HelloWorld.jar">
              <fileset dir="${build.classes.dir}">
                 <include name="**/*.class" />
              </fileset>
              <metainf dir="${src.dir}/META-INF">
                 <include name="*.xml" />
              </metainf>
        </jar>
    </target>
    <target name="clean">
        <delete dir="${build.dir}" />
    </target>
</project>

上面建立了一个名为 HelloWorld 的 Ant 项目,default="ejbjar"指定运行 Ant 时,如果没有给定任务名称,则默认执行 ejbjar 任务。basedir="."指定项目的路径为 build.xml 文件所在目录。
<property environment="env" />用于引用操作系统的环境变量。
<property name="jboss.home" value="${env.JBOSS_HOME}" />定义了一个名为 jboss.home 的属性,它的值引用名为 JBOSS_HOME 的环境变量(环境变量 JBOSS_HOME 是在安装 jboss 时让大家设置的)。
<property name="build.dir" value="${basedir}/build" />定义一个名为 build.dir 的属性,它的值指向项目路径下 build目录,该目录用于存放编绎后的临时文件。
<property name="build.classes.dir" value="${build.dir}/classes" />定义一个名为 build.dir 的属性,它的值指向项目路径下 build/ classes 目录,该目录用于存放编绎后的 class 文件。
<path id="build.classpath">节点定义了一个 id 为 build.classpath 的类路径,类路径包含[jboss 安装目录]\client 下的所有 jar 文件及/build/ classes 下的所有类文件。
<target name="prepare" depends="clean">节点用于在项目路径下创建 build 和/build/ classes 文件夹。该任务依赖clean 任务,执行 prepare 任务前会先执行 clean 任务。
<target name="compile" depends="prepare" description="编绎">节点定义了一个编绎任务,该任务调用 javac 对 src目录下的源文件进行编绎。classpath 引用 id 为 build.classpath 的类路径。编绎后的 class 文件存放在/build/classes目录,在任务执行前会先执行 prepare 任务。
<target name="ejbjar" depends="compile" description="创建 EJB 发布包">节点定义了一个打包任务,该任务调用 jar命令对/build/classes 目录下的所有 class 文件进行打包,并且把 src/META-INF 目录下的所有 xml 文件打进 jar 文件的 META-INF 目录。生成后的jar文件存放在项目的根目录下,名为 HelloWorld.jar。在任务执行前会先执行 compile任务。

当 build.xml 编写完成后,我们可以在 eclipse 中执行 Ant 任务。方法是:打开 build.xml 文件,在窗口右边的 Outline(大纲)中右键点击任务名称,在出现的菜单中点击“Run As(运行方式)”-“Ant Build(Ant 构建)”

如果你的 eclipse 中没有大纲窗口,你可以点击“window”-“show view(显示视图)-“Outline”

不管使用何种打包方式,一个 EJB 打包后应具有以下目录结构:
  EJB 应用根目录
  | -- **/*.class (你的.class 文件)
  | -- META-INF
          | -- MANIFEST.MF (如果使用工具打包,该文件由工具自动生成)

当 HelloWorld 打成 jar 文件后,我们把它发布到 Jboss。发布前先检查 jboss 是否已经启动,如果没有启动,我们可以进入[jboss 安装目录]/bin,  双击 run.bat 启动 Jboss。不指定启动参数的情况下,Jboss 默认使用 default 配置项。
把 jar 文件拷贝到[jboss 安装目录]\server\default\deploy\目录。观察 Jboss 控制台输出,如果没有抛出例外并看到下面的输出界面,发布就算成功了。

当 EJB 发布成功后,Jboss 容器会为它生成一个全局 JNDI 名称,我们可以利用这一点进一步判断 EJB 发布是否成功。我们进入 Jboss 的管理台查看它的 JNDI 名称,输入下面 URLhttp://localhost:8080/jmx-console/点击 service=JNDIView,查看 EJB 的 JNDI 名称。

在出现的页面中,找到“List of MBean operations:”栏。
点击“Invoke”按钮

在出现的页面中,我们可以看到 JBOSS 的 JNDI 树,它的命名约定如下:
(1)java:comp (java:comp namespace)
  这个上下文环境和其子上下文环境仅能被应用组件内部访问和使用
(2)java:(java: Namespace)
  子上下文环境和绑定的对象只能被处在同一个 JVM 内的客户访问
(3)Global JNDI Namespace
  上下文环境能被所有客户访问,不管它们是否处在同一个 JVM 内。

当 EJB 发布到 Jboss 时,如果我们没有为它指定全局JNDI名称或修改过其默认EJB名称,Jboss就会按照默认的命名规则为 EJB 生成全局 JNDI 名称,默认的命名规则如下:
如果把 EJB 作为模块打包进后缀为*.ear 的 JAVA EE 企业应用文件,默认的全局 JNDI 名称是本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local远程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remoteEAR-FILE-BASE-NAME 为 ear 文件的名称,EJB-CLASS-NAME 为 EJB 的非限定类名。
例: HelloWorld 应用作为 EJB 模块打包进名为 HelloWorld.ear 的企业应用文件,把它的远程接口的 JNDI 名称是:
HelloWorld/HelloWorldBean/remote
如果把 EJB 应用打包成后缀为*.jar 的模块文件,默认的全局 JNDI 名称是
本地接口:EJB-CLASS-NAME/local
远程接口:EJB-CLASS-NAME/remote
例:把 HelloWorld 应用打包成 HelloWorld.jar 文件,它的远程接口的 JNDI 名称是:HelloWorldBean/remote注意:EJB-CLASS-NAME 是不带包名的,如 com.foshanshop.ejb3.impl.HelloWorldBean 只需取 HelloWorldBean。如果你通过@Stateless.name()、     @Stateful.name()及其等价的 XML 指定了 EJB 名称,那么上面的 EJB-CLASS-NAME应该换为 EJB 名称,此时的 JNDI 名称格式如:EJB 名称/remote、EAR 文件名/EJB 名称/remote。

在 Global JNDI Namespace 一栏,我们看到了 HelloWorldBean 的远程接口的 JNDI 名称为 HelloWorldBean/remote。意味着 EJB 已经发布成功。接下来我们看看客户端如何访问它。
Test.jsp
<%@ page contentType="text/html; charset=GBK"%>
 <%@ page import="com.foshanshop.ejb3.HelloWorld, javax.naming.*,
 java.util.Properties"%>
 <%
        Properties props = new Properties();
        props.setProperty("java.naming.factory.initial",
 "org.jnp.interfaces.NamingContextFactory");
        props.setProperty("java.naming.provider.url", "localhost:1099");
        try {
            InitialContext ctx = new InitialContext(props);
            HelloWorld helloworld = (HelloWorld)
 ctx.lookup("HelloWorldBean/remote");
            out.println(helloworld.SayHello("佛山人"));
        } catch (NamingException e) {
            out.println(e.getMessage());
        }
 %>
  • 大小: 20 KB
分享到:
评论

相关推荐

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

    开发一个有状态会话Bean需要继承javax.ejb.SessionBean接口,并实现相应的生命周期方法,如ejbCreate()、ejbRemove()、ejbPassivate()、ejbActivate()等。 5. 部署到应用服务器 在部署到应用服务器时,需要配置ejb...

    Eclipse+Jboss EJB技术 会话Bean

    在EJB中,会话Bean分为两种类型:无状态会话Bean(Stateless Session Bean)和有状态会话Bean(Stateful Session Bean)。无状态会话Bean不保留任何客户端特定的信息,每次调用都是独立的。而有状态会话Bean则可以...

    EJB3 示例有状态和无状态会话bean

    - **会话Bean (Session Bean)**:分为有状态和无状态两种,用于封装业务逻辑操作。 - **消息驱动Bean (Message-Driven Bean)**:处理JMS(Java Message Service)消息。 ### 2. 有状态会话Bean (Stateful Session ...

    Jboss下开发ejb应用之一会话bean的应用

    会话Bean有两类:无状态会话Bean(Stateless Session Beans)和有状态会话Bean(Stateful Session Beans)。 1. 无状态会话Bean:适用于一次性的、与特定客户上下文无关的操作,如计算或查询。 2. 有状态会话Bean:...

    无状态会话Bean实验指导.doc

    【无状态会话Bean实验指导】的文档主要涵盖了如何开发和测试无状态Session Bean的步骤,这是企业级JavaBeans(EJB)技术的一部分,属于中间件领域的知识。EJB是Java平台上的一个标准,用于构建可扩展、可靠的分布式...

    EJB3.0源代码,包含会话Bean,实体Bean,还有消息Bean

    - **有状态会话Bean (Stateful Session Beans)**: 能够保持与特定客户端会话的状态,通常用于管理购物车或游戏状态等场景。 2. **实体Bean (Entity Beans)** - **容器管理的持久性 (Container-Managed ...

    EJB 会话BEAN PPT

    会话Bean是EJB中处理客户端交互的组件,根据其状态,会话Bean分为有状态会话Bean(Stateful Session Beans)和无状态会话Bean(Stateless Session Beans)。 1. **无状态会话Bean**:无状态会话Bean不会持久保存...

    Bean开发实例之二有状态会话Bean开发实例

    public class CartBean implements javax.ejb.SessionBean, java.io.Serializable { private String cardHolderName; private String creditCardNumber; private Vector&lt;Item&gt; items; public void ejbCreate...

    关于有状态和无状态会话bean的解释

    **无状态会话Bean(Stateless Session Bean)** 无状态会话Bean是最常见的类型,它们不保存任何特定客户端的状态。每次调用方法时,容器都会为请求分配一个新的会话Bean实例,因此每个客户端请求都是独立的。这意味...

    EJB3开发第一个无状态会话bean

    无状态会话 Bean(Stateless Session Bean)是企业级 Java(EJB)3.0 中的核心组件,主要用于实现业务逻辑,它不保存任何特定客户端的状态信息。本篇文章将深入讲解如何在 EJB3 中开发第一个无状态会话 Bean,以及...

    ejb.zip_单身会话bean

    首先,我们要理解“有状态会话bean”(Stateful Session Bean,SFSB)。与无状态会话bean相反,SFSB能够维护与客户端交互的上下文信息,也就是说,它们可以记住客户端的状态。这使得SFSB非常适合那些需要跟踪用户...

    Stateful--sessionbean.zip_sessionBean_stateful

    标题"Stateful--sessionbean.zip_sessionBean_stateful"表明这个压缩包包含有关有状态会话Bean的实现资料,可能包括设计思路、步骤截图和源代码。这些资源对于理解如何创建和使用SFSB至关重要。 描述中的"有状态的...

    实验6-无状态会话bean.docx

    3. 创建无状态会话bean:在新创建的包中,通过“New”-&gt;“EJB3 Session Bean”生成bean,设定Session Type为Stateless,并为bean提供Local和Remote接口。 4. 声明业务方法:在Remote接口中定义公共方法,如计算个人...

    实验6-无状态会话bean.pdf

    【实验6-无状态会话bean】主要涉及的是Java企业级应用开发中的核心概念——无状态会话Bean(Stateless Session Bean),这是Java EE(Java Platform, Enterprise Edition)规范中的重要组成部分,主要用于处理业务...

    学习SessionBean

    会话Bean可以保持与特定客户端的会话状态,即使客户端请求在多个方法调用之间进行。这种特性使得SessionBean成为构建Web应用程序和服务的理想选择,特别是在需要管理用户状态或执行复杂的业务流程时。 ### 2. ...

    Session Bean的使用

    不同于Stateful Session Bean(保持状态的会话bean),每个客户端请求都会创建一个新的bean实例,并保存其状态,Stateless Session Bean(无状态会话bean)不存储任何客户端特定的信息。这意味着无状态会话bean对于...

    ejb实例包括session bean和实体bean

    1. **Stateful Session Bean**:状态ful会话Bean保留了与特定客户端会话相关联的状态信息。这意味着它能够跟踪客户端的状态,例如购物车中的商品,从而提供个性化的服务。 2. **Stateless Session Bean**:无状态...

    JavaEE5网络鲜花店(有状态会话Bean)

    1. **有状态会话Bean(Stateful Session Bean, SFSB)**:有状态会话Bean是JavaEE中的一种组件,用于模拟服务器端的持久会话。与无状态会话Bean不同,SFSB能够记住客户的状态信息,例如购物车中的商品列表。这种设计...

Global site tag (gtag.js) - Google Analytics