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

无状态会话的ejb

在本文中,我们将了解如何在简单的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类的代码:

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的最终项目结构为:

ejb-项目结构

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

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

新动态网络项目

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

部门分配

7.创建一个新的Servlet

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

新的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具有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

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

mysql终端

下载Eclipse项目

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

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

无状态会话的ejb

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346995.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ArrayList源码学习笔记(3)

时隔两年&#xff0c;重新读ArrayList源码&#xff0c;轻松了很多&#xff0c;以问题的方式记录一下收获 装饰器模式 注释中提到ArrayList本身不是线程安全的&#xff0c;注释如下&#xff1a; * <p><strong>Note that this implementation is not synchronized.&…

【MFC系列-第10天】非模式对话框开发

10.1 程序左上角图标设置 通过SendMessage发送WM_SETICON消息来设置 10.2 纯Win32程序开发和技巧&#xff08;借助MFC源码&#xff09; 10.3 非模式对话框的调用 a)调用CDialog::Create函数来创建&#xff0c;并且调用ShowWindow来显示&#xff1b; b)单例模式每次判断句柄…

Maven教程之春

1.简介 在本文中&#xff0c;我们将演示如何针对非常特定的用例对Spring使用Maven依赖项。 我们使用的所有库的最新版本都可以在Maven Central上找到。 对于一个有效的构建周期而言&#xff0c;了解Maven依赖项的工作方式以及如何对其进行管理非常重要&#xff0c;并且对于在我…

【MFC系列-第11天】CWinApp类成员分析

11.1 资源管理器开发&#xff08;C语言&#xff09; 三种位运算 //#include <AtlBase.h> //混合 c_file.attrib | _A_HIDDEN|_A_RDONLY; //判断使用if(c_file.attrib & _A_HIDDEN) //删除属性c_file.attrib&~_A_HIDDENT;11.2 资源管理器开发&#xff08;API&a…

【MFC系列-第12天】Windows系统对话框

12.1 INI配置文件 UINT GetProfileInt( LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault ); 从应用程序的配置文件&#xff08;.INI&#xff09;的一个配置项中获取一个整数 CString GetProfileString(LPCTSTR szSection, LPCTSTR szEntry, LPCTSTR szDefault NULL )…

【BCH码2】BCH码的快速BM迭代译码原理详解及MATLAB实现(不使用MATLAB库函数【全部代码需私信另外付费获取】)

理论基础 订阅《信道编码》专栏,首先查阅各子程序的详解 【有限域生成】本原多项式生成有限域的原理及MATLAB实现 【有限域除法】二元多项式除法电路原理及MATLAB详解 【有限域元素加法和乘法】有限域元素加法和乘法的原理及MATLAB实现 【多元域乘法】多项式乘法电路原理…

【MFC系列-第13天】Windows系统对话框(对话框记事本逻辑)

13.1 内存泄露问题 真正的内存泄露是有循环性反复申请而不释放内存&#xff1a;是指在软件运行时&#xff0c;比如点一下某按钮就申请一次堆空间&#xff0c;而在下次申请前或者适当的时机及时释放内存&#xff1b; Detected memory leaks! Dumping objects -> {225} norm…

js 实现轻量ps_简单轻量的池实现

js 实现轻量ps对象池是包含指定数量的对象的容器。 从池中获取对象时&#xff0c;在将对象放回之前&#xff0c;该对象在池中不可用。 池中的对象具有生命周期&#xff1a;创建&#xff0c;验证&#xff0c;销毁等。池有助于更好地管理可用资源。 有许多使用示例。 特别是在应用…

【MFC系列-第14天】MFC核心类库的成员介绍(记事本快捷键)

14.1 对话框快捷键的设置和加载 a) 插入一个新的Accelerator到资源里&#xff0c;把加速键和对应的响应控件(如一个按钮)关联 b) 在对话框头文件中声明 HACCEL m_hAccel;c) 在对话框的构造函数里初始化m_hAccel m_hAccel ::LoadAccelerators(AfxGetInstanceHandle(),MAKEI…

【MFC系列-第15天】关联变量的概念与用法

15.1 权限管理对话框的信息录入与保存 15.2 控件型关联变量&#xff1a; FromHandle和DeleteTempMap管理成员对象表&#xff0c;前者由HWND获取CWnd*&#xff0c;后者进行删除。 BOOL Attach( HWND hWndNew ); //关联 HWND Detach( ); //解除关联 BOOL SubclassWindow( HWND…

【MFC系列-第16天】企业信息管理软件开发

常见的两种类和类之间相互调用的方法。 16.1 用户权限信息在不同对话框之间共享 ①在CWokerApp类中定义变量&#xff1a; class CWorkerApp : public CWinApp { public:CWorkerApp();SAdmin m_admin;//登录信息 // 重写 public:virtual BOOL InitInstance(); // 实现DECLARE…

java微妙_编码Java时的10个微妙的最佳实践

java微妙这是10条最佳实践的列表&#xff0c;这些最佳实践比您的平均Josh Bloch有效Java规则要微妙得多。 尽管Josh Bloch的列表很容易学习&#xff0c;并且涉及日常情况&#xff0c;但此处的列表包含了涉及API / SPI设计的较不常见的情况&#xff0c;尽管这些情况可能会产生很…

【MFC系列-第17天】企业信息管理软件开发

关注公号【逆向通信猿】更精彩&#xff01;&#xff01;&#xff01; 17.1 数值型关联变量&#xff1a; a)在MFC中有部分控件支持数值型关联变量&#xff1a; 编辑控件、下拉控件、单选按钮、复选框以及日期控件&#xff1b; b)在类向导中为控件建立关联变量时&#xff0c;选…

GraphQL在Wildfly群上

“ GraphQL是API的查询语言&#xff0c;是用于使用现有数据完成这些查询的运行时。 GraphQL为您的API中的数据提供了一个完整且易于理解的描述&#xff0c;使客户能够准确地询问他们所需的内容&#xff0c;仅此而已&#xff0c;使随着时间的推移更容易开发API并启用强大的开发人…

【MFC系列-第18天】企业信息管理软件开发

关注公号【逆向通信猿】更精彩&#xff01;&#xff01;&#xff01; CWnd类中常用的成员函数 函数名称含义static CWnd* PASCAL GetActiveWindow( )&#xff08;进程内的&#xff09;获取活动窗口CWnd* SetActiveWindow( )&#xff08;进程内的&#xff09;将一个窗口设置为…

【MFC系列-第19天】初步认识GDI绘图技术

WM_PAINT消息测试 调试输出字符串 OutputDebugSting(_T(“WM_PAINT-OnPaint\n”));1、WM_PAINT&#xff1a;功能和发生时间 2、BeginPaint和EndPaint必须成对使用。 a)BeginPaint返回的DC句柄&#xff0c;是基于关联的窗口客户区坐标系绘图 b)MFC把这两个函数封装为一个类…

javafx 示例_示例介绍:JavaFX 8打印

javafx 示例我有一段时间没有写博客了&#xff0c;我想与其他人分享有关JavaFX的所有信息&#xff08;我的日常工作和家庭可能是借口&#xff09;。 对于那些对此博客不熟悉的人 &#xff0c;我是JavaFX 2 Introduction by Example&#xff08;JIBE&#xff09;的作者&#xff…

【MFC系列-第20天】CDC绘图类成员介绍

20.1 三大坐标系&#xff1a;屏幕、客户区和非客户区 20.2 三大派生类&#xff1a; a)CPaintDC(客户区标准绘图&#xff09;,内部封装函数是&#xff1a;BeginPaint和EndPaint b)CClientDC&#xff08;客户区非标准绘图&#xff09;,内部是&#xff1a;::GetDC和ReleaseDC …

Spring Data JPA教程

在Java类或对象与关系数据库之间管理数据是一项非常繁琐且棘手的任务。 DAO层通常包含许多样板代码&#xff0c;应简化这些样板代码&#xff0c;以减少代码行数并使代码可重复使用。 在本教程中&#xff0c;我们将讨论Spring数据的JPA实现。 1.简介 1.1什么是JPA&#xff1f;…

【MFC系列-第21天】GDI算法实战——过渡色

21.1 Caption过渡色实现 // 方法一 void CCaptionDlg::DrawColorTitle(CRect rect, COLORREF col1, COLORREF col2,CDC* pDC) {int cx rect.Width();int red GetRValue(col2) - GetRValue(col1);int green GetGValue(col2) - GetGValue(col1);int blue GetBValue(col2) -…