无状态会话的ejb_Java EE状态会话Bean(EJB)示例
無(wú)狀態(tài)會(huì)話的ejb
在本文中,我們將了解如何在簡(jiǎn)單的Web應(yīng)用程序中使用狀態(tài)會(huì)話Bean來(lái)跟蹤客戶端會(huì)話中的狀態(tài)。
1.簡(jiǎn)介
有狀態(tài)會(huì)話Bean通常保存有關(guān)特定客戶端會(huì)話的信息,并在整個(gè)會(huì)話中保留該信息(與無(wú)狀態(tài)會(huì)話Bean相對(duì))。 有狀態(tài)EJB實(shí)例僅與一個(gè)客戶端耦合。 當(dāng)然,一個(gè)客戶端可以擁有許多EJB實(shí)例。
在此示例中,我們將創(chuàng)建一個(gè)簡(jiǎn)單的Shopping Cart應(yīng)用程序。 會(huì)話bean將保存產(chǎn)品列表。 隨著客戶將更多產(chǎn)品添加到購(gòu)物車(chē)中,此列表將相應(yīng)增加。 最終,客戶將能夠簽出他的訂單,并且上述列表中的產(chǎn)品將保存在MySQL數(shù)據(jù)庫(kù)中。
為了實(shí)現(xiàn)上述功能,我們將創(chuàng)建一個(gè)EAR項(xiàng)目和一個(gè)EJB項(xiàng)目來(lái)托管我們的會(huì)話Bean,并創(chuàng)建一個(gè)動(dòng)態(tài)Web應(yīng)用程序來(lái)托管Servlet,以測(cè)試上述行為。 我們將使用Eclipse Java EE IDE 4,3 Kepler和Glassfish 4.0作為我們的容器。 另外,我們將使用標(biāo)準(zhǔn)的JPA 2.o將我們的產(chǎn)品保存在在localhost上運(yùn)行MySQL 5.6.14數(shù)據(jù)庫(kù)中。 這是有關(guān)如何將MySQL與Glassfish集成的指南。
2.創(chuàng)建一個(gè)新的企業(yè)應(yīng)用程序項(xiàng)目
創(chuàng)建一個(gè)名為StatefulEJBEAR的新企業(yè)應(yīng)用程序項(xiàng)目。 在Eclipse IDE中,選擇File-> New-> Enterprise Application Project,填寫(xiě)表單,然后單擊Finish:
3.創(chuàng)建一個(gè)新的EJB Projet
創(chuàng)建一個(gè)名為StatefulSessionBeansEJB的新EJB項(xiàng)目。 我們將基于此創(chuàng)建會(huì)話bean。 轉(zhuǎn)到文件->新建-> EJB項(xiàng)目并填寫(xiě)表單。 請(qǐng)小心選擇“添加EAR項(xiàng)目”,然后選擇“ StatefulEJBEAR ”作為EAR項(xiàng)目名稱(chēng):
4.創(chuàng)建一個(gè)有狀態(tài)會(huì)話Bean
在項(xiàng)目資源管理器中打開(kāi)StatefulSessionBeansEJB項(xiàng)目,并在文件夾ejbModule創(chuàng)建一個(gè)名為com.javacodegeeks.enterprise.ejb的新源包。 在該程序包中,創(chuàng)建一個(gè)新的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();}如您所見(jiàn),我們聲明了兩種方法,一種方法是將產(chǎn)品添加到購(gòu)物車(chē),另一種方法是檢查訂單。
這是會(huì)話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();} }如您所見(jiàn),我們的Session bean實(shí)現(xiàn)了我們的Cart接口,并且僅保存了一個(gè)產(chǎn)品列表(稍后將在類(lèi)Product )。
在上面的代碼中注意:
- 我們使用@Stateful將類(lèi)注釋為有狀態(tài)會(huì)話Bean。
- 我們使用@StatefulTimeout(unit = TimeUnit.MINUTES, value = 20)注釋聲明超時(shí)。 此超時(shí)表示bean應(yīng)該存在的時(shí)間,因此對(duì)于會(huì)話有效。 它應(yīng)與HTTP會(huì)話超時(shí)值相對(duì)應(yīng)。
- 我們使用@PersistenceContext注入一個(gè)EntityManager來(lái)處理產(chǎn)品的持久性。
- 我們?cè)趐rivate void initializeBean()方法上使用@PostConstruct批注。 這將指示EJB容器在bean初始化時(shí)執(zhí)行該方法。 您可以將其視為構(gòu)造函數(shù)。
- 我們?cè)趐ublic void checkOut()方法上使用@TransactionAttribute(TransactionAttributeType.REQUIRED)批注。 需要使用此注釋來(lái)表示容器將在事務(wù)上下文中調(diào)用業(yè)務(wù)方法。 您可以按照這種方法查看列表中的產(chǎn)品,并將它們保留在數(shù)據(jù)庫(kù)中。
5.產(chǎn)品實(shí)體類(lèi)
這是代表我們購(gòu)物車(chē)應(yīng)用程序中的簡(jiǎn)單產(chǎn)品的對(duì)象。 它由一個(gè)ID和一個(gè)類(lèi)型組成。 就像我們說(shuō)過(guò)的,當(dāng)結(jié)帳時(shí),我們希望購(gòu)物車(chē)上的產(chǎn)品能夠保存在數(shù)據(jù)庫(kù)中。 我們使用JPA 2.0批注將Product類(lèi)映射到MySQL表。 在此示例中,我創(chuàng)建了一個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù),名為shop和表,該表使用腳本創(chuàng)建,名稱(chēng)為product :
MySQL產(chǎn)品表創(chuàng)建腳本:
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類(lèi)的代碼:
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;}}以上注釋是不言自明的。 非常簡(jiǎn)單地,我們使用:
- @Entity將類(lèi)聲明為Entity。
- @Table(name = "PRODUCT", catalog = "shop")顯示該類(lèi)將映射到名為shop的數(shù)據(jù)庫(kù)中名為product的表。
- @Id id , @Id @GeneratedValue(strategy = GenerationType.IDENTITY)聲明類(lèi)Product的字段id將是相應(yīng)數(shù)據(jù)庫(kù)表的主鍵。
- @Column將類(lèi)字段映射到表product的數(shù)據(jù)庫(kù)列。
最后,為了使持久性起作用,我們需要在ejbModule/META-INF文件夾中創(chuàng)建一個(gè)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>確保使用此隊(duì)列已將MySQL與Glassfish正確集成。 有關(guān)persistence.xml文件的更多信息,請(qǐng)參見(jiàn)此Oracle指南 。
因此, StatefulBeansEJB的最終項(xiàng)目結(jié)構(gòu)為:
6.創(chuàng)建一個(gè)新的動(dòng)態(tài)Web項(xiàng)目
轉(zhuǎn)到文件->新建->動(dòng)態(tài)Web項(xiàng)目。 填寫(xiě)表單,并確保選中“將項(xiàng)目添加到EAR”,然后將StatefulEJBEAR作為“ EAR項(xiàng)目名稱(chēng)”:
單擊“完成”后,轉(zhuǎn)到項(xiàng)目資源管理器,然后右鍵單擊項(xiàng)目StatefulSessionBeansTest然后轉(zhuǎn)到“屬性”->“部署程序集”->“添加”->“項(xiàng)目”->“ StatefulEJB”:
7.創(chuàng)建一個(gè)新的Servlet
轉(zhuǎn)到StatefulSessionBeansTest Web項(xiàng)目,并創(chuàng)建一個(gè)名為ShoppingCartServlet的新Servlet:
因此,這將是Web項(xiàng)目的最終結(jié)構(gòu):
這是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中,當(dāng)用戶第一次發(fā)送GET請(qǐng)求時(shí),將從容器中獲取一個(gè)新的CartBean實(shí)例并將其添加到會(huì)話中。 然后,解析product查詢參數(shù),如果它不為null,則將創(chuàng)建productName具有productName type的新Product ,并將其添加到會(huì)話bean中的產(chǎn)品列表中。
然后,對(duì)checkout查詢參數(shù)進(jìn)行解析,如果將其評(píng)估為'yes' ,則會(huì)話Bean中的產(chǎn)品將被保留。
提示: 如果您在確定EJB PassivationObject的可移植JNDI名稱(chēng)時(shí)遇到麻煩,請(qǐng)?jiān)诓渴痦?xiàng)目時(shí)查看Glassfish的日志或輸出,您會(huì)發(fā)現(xiàn)這樣的一行: 2013-12-13T18:22:28.598 + 0200 | INFO :EJB5181:EJB PassivationObject的便攜式JNDI名稱(chēng):(java:global / StatefulBeans / StatefulEJB / PassivationObject,java:global / StatefulBeans / StatefulEJB / PassivationObject!com.javacodegeeks.enterprise.ejb.Passivation)
8.測(cè)試
現(xiàn)在,我們僅要將Dynamic Web Application部署到Glassfish,并在購(gòu)物車(chē)中添加一些產(chǎn)品。 然后,我們將要求結(jié)帳該訂單。
假設(shè)我們要添加一些產(chǎn)品,我們可以發(fā)出以下請(qǐng)求:
http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=ram http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=mouse http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=ssd發(fā)布這些請(qǐng)求時(shí),這是控制臺(tái)的輸出:
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現(xiàn)在要簽出訂單,您可以發(fā)出:
http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?checkout=yes這是控制臺(tái)的輸出:
2014-01-07T22:19:46.444+0200|INFO: Hello from servlet 2014-01-07T22:19:46.537+0200|INFO: Shopping cart checked out在這里您可以看到數(shù)據(jù)庫(kù)中的產(chǎn)品:
下載Eclipse項(xiàng)目
這是Java EE狀態(tài)會(huì)話Bean(EJB)上的示例。 以下是此示例的Eclipse項(xiàng)目: StatefulEJBS.zip
翻譯自: https://www.javacodegeeks.com/2013/08/java-ee-stateful-session-bean-ejb-example.html
無(wú)狀態(tài)會(huì)話的ejb
總結(jié)
以上是生活随笔為你收集整理的无状态会话的ejb_Java EE状态会话Bean(EJB)示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 安卓手机照片删除怎么恢复
- 下一篇: Maven教程之春