在本文中,我们将了解如何在简单的Web应用程序中使用状态会话Bean来跟踪客户端会话中的状态。

1.简介

有状态会话Bean通常保存有关特定客户端会话的信息,并在整个会话中保留该信息(与无状态会话Bean相对)。 有状态EJB实例仅与一个客户端耦合。 当然,一个客户端可以拥有许多EJB实例。

在此示例中,我们将创建一个简单的Shopping Cart应用程序。 会话bean将保存产品列表。 随着客户将更多产品添加到购物车中,此列表将相应增加。 最终,客户将能够签出他的订单,并且上述列表中的产品将保存在MySQL数据库中。

为了实现上述功能,我们将创建一个EAR项目和一个EJB项目来托管我们的会话Bean,并创建一个动态Web应用程序来托管一个Servlet,以测试上述行为。 我们将使用Eclipse Java EE IDE 4,3 Kepler和Glassfish 4.0作为容器。 另外,我们将使用标准的JPA 2.o将我们的产品保存在在localhost上运行的MySQL 5.6.14数据库中。 这是有关如何将MySQL与Glassfish集成的指南。

2.创建一个新的企业应用程序项目

创建一个名为StatefulEJBEAR的新企业应用程序项目。 在Eclipse IDE中,选择File-> New-> Enterprise Application Project,填写表单,然后单击Finish:

3.创建一个新的EJB Projet

创建一个名为StatefulSessionBeansEJB的新EJB项目。 我们将基于此创建会话bean。 转到文件->新建-> EJB项目并填写表单。 请小心选择“添加EAR项目”,然后选择“ StatefulEJBEAR ”作为EAR项目名称:

4.创建一个有状态会话Bean

在项目资源管理器中打开StatefulSessionBeansEJB项目,并在文件夹ejbModule创建一个名为com.javacodegeeks.enterprise.ejb的新源包。 在该程序包中,创建一个新的Interface ,它将是EJB的本地视图:

Cart.java:

package com.javacodegeeks.enterprise.ejb;import javax.ejb.Local;import com.javacodegeeks.enterprise.product.Product;@Local
public interface Cart {void addProductToCart(Product product);void checkOut();}

如您所见,我们声明了两种方法,一种方法是将产品添加到购物车,另一种方法是检查订单。

这是会话Bean:

CartBean.java:

package com.javacodegeeks.enterprise.ejb;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;import javax.annotation.PostConstruct;
import javax.ejb.Stateful;
import javax.ejb.StatefulTimeout;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;import com.javacodegeeks.enterprise.product.Product;@Stateful
@StatefulTimeout(unit = TimeUnit.MINUTES, value = 20)
public class CartBean implements Cart {@PersistenceContext(unitName = "pu", type = PersistenceContextType.EXTENDED)private EntityManager entityManager;private List products;@PostConstructprivate void initializeBean(){products = new ArrayList<>();}@Overridepublic void addProductToCart(Product product) {products.add(product);}@Override@TransactionAttribute(TransactionAttributeType.REQUIRED)public void checkOut() {for(Product product : products){entityManager.persist(product);}products.clear();}
}

如您所见,我们的Session bean实现了我们的Cart接口,并简单地保存了一个产品列表(稍后将在类Product上提供更多信息)。

在上面的代码中注意:

  • 我们使用@Stateful将类注释为有状态会话Bean。
  • 我们使用@StatefulTimeout(unit = TimeUnit.MINUTES, value = 20)注释声明超时。 此超时表示bean应该存在的时间,因此对于会话有效。 它应该与HTTP会话超时值相对应。
  • 我们使用@PersistenceContext注入一个EntityManager来处理产品的持久性。
  • 我们在private void initializeBean()方法上使用@PostConstruct批注。 这将指示EJB容器在bean初始化时执行该方法。 您可以将其视为构造函数。
  • 我们在public void checkOut()方法上使用@TransactionAttribute(TransactionAttributeType.REQUIRED)批注。 需要使用此注释来表示容器将要在事务上下文中调用业务方法。 您可以按照这种方法查看列表中的产品,并将它们保留在数据库中。

5.产品实体类

这是代表我们购物车应用程序中简单产品的对象。 它由一个ID和一个类型组成。 就像我们说过的,当结帐时,我们希望购物车上的产品能够保存在数据库中。 我们使用JPA 2.0批注将Product类映射到MySQL表。 对于此示例,我创建了一个简单的数据库,名为shop和表,其表名为product ,该脚本是使用以下脚本创建的:

MySQL产品表创建脚本:

CREATE TABLE `product` (`ID` int(11) NOT NULL AUTO_INCREMENT,`TYPE` varchar(256) COLLATE utf8_unicode_ci NOT NULL,PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

这是表格:

让我们看一下Product类的代码:

产品.java:

package com.javacodegeeks.enterprise.product;import java.io.Serializable;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;@Entity
@Table(name = "PRODUCT", catalog = "shop")
public class Product implements Serializable {private static final long serialVersionUID = 1L;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "ID", nullable = false)private int id;@Column(name = "TYPE", nullable = false)private String type;public int getId() {return id;}public String getType() {return type;}public void setType(String description) {this.type = description;}}

以上注释不言自明。 非常简单地,我们使用:

  • @Entity将类声明为Entity。
  • @Table(name = "PRODUCT", catalog = "shop")显示该类将映射到名为shop的数据库中名为product的表。
  • @Id id@Id @GeneratedValue(strategy = GenerationType.IDENTITY)声明类Product的字段id将是相应数据库表的主键。
  • @Column将类字段映射到表product的数据库列。

最后,为了使持久性起作用,我们需要在ejbModule/META-INF文件夹内创建一个persistence.xml文件。 该文件如下所示:

application.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"version="2.0"><persistence-unit name="pu" transaction-type="JTA"><jta-data-source>jdbc/MySQLDataSource</jta-data-source> <class>com.javacodegeeks.enterprise.product.Product</class></persistence-unit></persistence>

确保使用此队列已将MySQL与Glassfish正确集成。 有关persistence.xml文件的更多信息,请参见此Oracle指南 。

因此, StatefulBeansEJB的最终项目结构为:

6.创建一个新的动态Web项目

转到文件->新建->动态Web项目。 填写表单,确保您选中“将项目添加到EAR”,并将StatefulEJBEAR用作“ EAR项目名称”:

单击“完成”后,转到项目资源管理器,然后右键单击项目StatefulSessionBeansTest然后转到“属性”->“部署程序集”->“添加”->“项目”->“ StatefulEJB”:

7.创建一个新的Servlet

转到StatefulSessionBeansTest Web项目并创建一个名为ShoppingCartServlet的新Servlet:

因此,这将是Web项目的最终结构:

这是Servlet的代码:

ShoppingCartServlet.java:

package com.javacodegeeks.enterprise.servlet;import java.io.IOException;import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.javacodegeeks.enterprise.ejb.Cart;
import com.javacodegeeks.enterprise.product.Product;@WebServlet("/ShoppingCartServlet")
public class ShoppingCartServlet extends HttpServlet {private static final long serialVersionUID = 1L;private static final String CART_SESSION_KEY = "shoppingCart";public ShoppingCartServlet() {super();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("Hello from servlet");Cart cartBean = (Cart) request.getSession().getAttribute(CART_SESSION_KEY);if(cartBean == null){// EJB is not yet in the HTTP session// This means that the client just sent his first request// We obtain a CartBean instance and add it to the session object.try {InitialContext ic = new InitialContext();cartBean = (Cart) ic.lookup("java:global/StatefulEJBEAR/StatefulSessionBeansEJB/CartBean!"+ "com.javacodegeeks.enterprise.ejb.Cart");request.getSession().setAttribute(CART_SESSION_KEY, cartBean);System.out.println("shoppingCart created");} catch (NamingException e) {throw new ServletException(e);}}String productName = request.getParameter("product");if(productName != null && productName.length() > 0){Product product = new Product();product.setType(productName);cartBean.addProductToCart(product);System.out.println("product "+productName+" added");}String checkout = request.getParameter("checkout");if(checkout != null && checkout.equalsIgnoreCase("yes")){// Request instructs to complete the purchasecartBean.checkOut();System.out.println("Shopping cart checked out ");}}}

在上面的Serlvet中,当用户第一次发送GET请求时,将从容器中获取一个新的CartBean实例并将其添加到会话中。 然后,解析product查询参数,如果它不为null,则将使用productName type的新Product并将其添加到会话bean中的产品列表中。

然后,分析checkout查询参数,如果将其评估为'yes' ,则会话Bean中的产品将被保留。

提示: 如果您在确定EJB PassivationObject的可移植JNDI名称时遇到麻烦,请在部署项目时查看Glassfish的日志或输出,您会发现类似以下内容的行: 2013-12-13T18:22:28.598 + 0200 | INFO :EJB5181:EJB PassivationObject的便携式JNDI名称:(java:global / StatefulBeans / StatefulEJB / PassivationObject,java:global / StatefulBeans / StatefulEJB / PassivationObject!com.javacodegeeks.enterprise.ejb.Passivation)

8.测试

现在,我们仅要将Dynamic Web Application部署到Glassfish,并在购物车中添加一些产品。 然后,我们将要求结帐该订单。

假设我们要添加一些产品,我们可以发出以下请求:

http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=ram
http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=mouse
http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=ssd

发布这些请求时,这是控制台的输出:

2014-01-07T22:02:07.622+0200|INFO: Hello from servlet
2014-01-07T22:02:07.684+0200|INFO: shoppingCart created
2014-01-07T22:02:07.687+0200|INFO: product ram added
2014-01-07T22:02:12.236+0200|INFO: Hello from servlet
2014-01-07T22:02:12.237+0200|INFO: product mouse added
2014-01-07T22:02:24.851+0200|INFO: Hello from servlet
2014-01-07T22:02:24.851+0200|INFO: product ssd added

现在要签出订单,您可以发出:

http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?checkout=yes

这是控制台的输出:

2014-01-07T22:19:46.444+0200|INFO: Hello from servlet
2014-01-07T22:19:46.537+0200|INFO: Shopping cart checked out

在这里您可以看到数据库中的产品:

下载Eclipse项目

这是Java EE状态会话Bean(EJB)上的示例。 这是此示例的Eclipse项目: StatefulEJBS.zip

翻译自: https://www.javacodegeeks.com/2013/08/java-ee-stateful-session-bean-ejb-example.html

Java EE状态会话Bean(EJB)示例相关推荐

  1. 无状态会话的ejb_Java EE状态会话Bean(EJB)示例

    无状态会话的ejb 在本文中,我们将了解如何在简单的Web应用程序中使用状态会话Bean来跟踪客户端会话中的状态. 1.简介 有状态会话Bean通常保存有关特定客户端会话的信息,并在整个会话中保留该信 ...

  2. 【Java Web开发指南】有状态会话Bean(SLSB) 和无状态会话Bean(SFSB)的区别

    有状态会话Bean(SLSB) 和无状态会话Bean(SFSB)的区别 1 无状态 (Stateless) 在不同方法调用间不保留任何状态 . 事务处理必须在一个方法中结束 . 通常资源占用较少:可以 ...

  3. 有状态会话Bean(SLSB)和无状态会话Bean(SFSB)的区别

    最近部门组织学习EJB3,到statelessbean和stateFul之间的区别这个地方卡壳了.原因是对这个没有深刻的理解.以下是它们的区别和应用场合. 1   无状态   (Stateless)  ...

  4. 无状态会话bean(1)---定义

    无状态会话bean用于完毕在单个方法的生命周期内的操作.无状态bean能够实现很多业务操作,可是每一个方法都不能假定不论什么其它的方法会在它之前调用.后半句的意思是如今的你可能不是刚才的你.明天的你可 ...

  5. java jax-rs_在Java EE 6中将Bean验证与JAX-RS集成

    java jax-rs JavaBeans验证(Bean验证)是Java EE 6平台的一部分提供的新验证模型. 约束通过以JavaBeans组件(例如托管Bean)的字段,方法或类上的注释形式的约束 ...

  6. 在Java EE 6中将Bean验证与JAX-RS集成

    JavaBeans验证(Bean验证)是一种新的验证模型,可作为Java EE 6平台的一部分使用. 约束条件支持Bean验证模型,该约束以注释的形式出现在JavaBeans组件(例如托管Bean)的 ...

  7. Weblogic10 + EJB3入门教程(1):编写第一个无状态会话Bean(Stateless Session Bean)...

    在本文主要介绍如何来开发一个Stateless Session Bean,并在未安装WebLogic10的机器上访问Session Bean.开发EJB3 Stateless Session Bean ...

  8. ejb+jpa_使用Arquillian(包括JPA,EJB,Bean验证和CDI)测试Java EE 6

    ejb+jpa 很长时间以来,我听到很多人对Arquillian说好话 . 尽管我一直在阅读有关其用法的文章,但实际上我无法在一篇文章中找到涵盖我认为重要的某些方面的文章. 当然,我看起来还不够努力. ...

  9. 使用Arquillian(包括JPA,EJB,Bean验证和CDI)测试Java EE 6

    很长时间以来,我听到很多人对Arquillian说好话 . 虽然我一直在阅读有关其用法的文章,但实际上我无法在一篇文章中找到涵盖我认为重要的某些方面的文章. 当然,我看起来还不够努力. 我要讲的要点是 ...

最新文章

  1. UNIX编程笔记:关于停止的进程接收信号的问题
  2. 300秒搞定第一超算1万年的计算量,量子霸权时代已来?
  3. 02JavaScript中的变量
  4. session与cookie的区别
  5. python elasticsearch模块_Python 操作 ElasticSearch
  6. python matlabplot animate 刷新_matlab动态绘图Animation
  7. 从零开始的C++网络编程
  8. 在正式使用计算机账务系统的银行对账功能,用友ERP-U8管理系统认证考试理论题...
  9. Python使用threading实现多线程
  10. testng依赖_TestNG依赖关系–DependOnMethods,dependsOnGroups
  11. Android客户端获取服务器的json数据(二)
  12. spring中bean的自动装配(详细)
  13. 最强面试题整理第一弹:Python 基础面试题(附答案)
  14. matlab投资组合权重,Matlab做投资组合最优化
  15. 好玩的Deep Dream模型
  16. 经济学基础(本)【1】
  17. Swing中如何实现二级联动下拉列表
  18. 基于java的中文分词工具ANSJ
  19. pvid与vid详解
  20. Python的一些基础实操练习题

热门文章

  1. Project编写功能点的规划时间
  2. mysql外键引用语法_mysql – 外键语法
  3. apache ignite_Kubernetes集群上的Apache Ignite和Spring第2部分:Kubernetes部署
  4. io.realm:rea_使Java具有响应性的框架和工具包:RxJava,Spring Reactor,Akka和Vert.x概述...
  5. javafx动画_JavaFX动画工具
  6. flex布局水平垂直 垂直_垂直和水平装饰
  7. jboss fuse 教程_在JBoss Fuse / Fabric8 / Karaf中使用Byteman
  8. 具有PreAuthorize的Spring方法安全性
  9. 詹金斯搭建_与詹金斯一起连续交付Heroku
  10. 如何在Java中转义JSON字符串-Eclipse IDE技巧