原文:http://zetcode.com/java/ejb/

在本教程中,我们学习如何使用 Enterprise JavaBeans。 我们使用 GlassFish,NetBeans,Derby 和 Maven。

Enterprise JavaBean (EJB) 是服务器端组件,封装了应用的业务逻辑。 EJB 在 EJB 容器中运行,该容器负责各种系统级服务,包括事务管理,安全性和并发控制。 EJB 是 Java EE 规范的一部分。

GlassFish 是 Java EE 的参考实现,它包括 Enterprise JavaBeans 容器。 我们将在 GlassFish 中运行示例。 Apache Derby 是完全用 Java 实现的开源关系数据库。 Oracle 以 Java DB 的名义分发相同的二进制文件。

第一个 EJB

我们在 NetBeans 中创建一个新的 Web 应用。 该项目将称为MyFirstEJB。 从“服务器和设置”页面,选择 GlassFish 服务器,并将上下文更改为myfirstejb

EJB 简介 - 图1

图:服务器和设置

在此对话框中,我们选择应用服务器,Java EE 版本和上下文路径。

index.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Test page</title>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. </head>
  8. <body>
  9. <p>Test page</p>
  10. </body>
  11. </html>

这是我们的index.html页面。 如果我们访问应用的根页面,它将返回。

我们右键单击应用图标,然后选择一个 Session Bean 类型的新 EJB。 我们将 bean 称为MyFirstBean,键入com.zetcode.ejb包,然后选择无状态会话类型。

EJB 简介 - 图2

图:在 NetBeans 中创建一个新的会话 Bean

无状态会话 Bean 不维护与客户端的对话状态。 当客户端调用无状态 Bean 的方法时,该 Bean 的实例变量可能包含特定于该客户端的状态,但仅在调用期间包含。 该方法完成后,客户端特定的状态将丢失。

FirstBean.java

  1. package com.zetcode.ejb;
  2. import javax.ejb.Stateless;
  3. @Stateless
  4. public class FirstBean {
  5. private String name;
  6. public String getName() {
  7. return name;
  8. }
  9. public void setName(String name) {
  10. this.name = name;
  11. }
  12. public String sayHello() {
  13. StringBuilder sb = new StringBuilder("Hello ");
  14. sb.append(this.getName()).append("!");
  15. return sb.toString();
  16. }
  17. }

MyFirstBean是无状态会话 Bean。 使用@Stateless装饰创建一个无状态会话 bean。 它具有no-interface view,其中不使用本地业务接口,并且 Bean 类的所有公共方法都自动向调用者公开。

  1. public String sayHello() {
  2. StringBuilder sb = new StringBuilder("Hello ");
  3. sb.append(this.getName()).append("!");
  4. return sb.toString();
  5. }

MyFirstBean's的工作是构造对调用者的问候。

接下来,我们通过右键单击项目图标并从 Web 类别中选择 Servlet 文件类型来创建一个新的 Servlet。 我们将 servlet 称为Greet,然后键入com.zetcode.web包。 我们将 URL 模式更改为/greet

EJB 简介 - 图3

图:创建新的 servlet

在新的 Servlet 对话框中,我们提供 Servlet 名称及其包。

Greet.java

  1. package com.zetcode.web;
  2. import com.zetcode.ejb.FirstBean;
  3. import java.io.IOException;
  4. import java.io.PrintWriter;
  5. import javax.ejb.EJB;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.annotation.WebServlet;
  8. import javax.servlet.http.HttpServlet;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11. @WebServlet(name = "Greet", urlPatterns = {"/greet"})
  12. public class Greet extends HttpServlet {
  13. @EJB
  14. private FirstBean firstBean;
  15. @Override
  16. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  17. throws ServletException, IOException {
  18. response.setContentType("text/plain;charset=UTF-8");
  19. firstBean.setName(request.getParameter("name"));
  20. String msg = firstBean.createMessage();
  21. try (PrintWriter out = response.getWriter()) {
  22. out.println(msg);
  23. }
  24. }
  25. }

Greet Servlet 从客户端发送的 URL 中读取名称参数,调用 EJB 的createMessage()业务方法,并以纯文本形式返回响应。

  1. @EJB
  2. private FirstBean firstBean;

@EJB注解将 EJB 注入 Servlet。

  1. response.setContentType("text/plain;charset=UTF-8");

servelt 响应以 UTF-8 字符集的纯文本格式显示。

  1. firstBean.setName(request.getParameter("name"));

我们从请求中检索name参数,并将其设置为 EJB。

  1. String msg = firstBean.createMessage();

我们将其称为createMessage()业务方法。

EJB 简介 - 图4

图:MyFirstEJB 项目结构

我们构建应用并将其部署到 GlassFish 服务器。 要构建应用,请右键单击项目图标,然后选择“构建”。 要部署应用,请右键单击项目图标,然后选择“部署”。

  1. $ curl localhost:8080/myfirstejb/greet?name=Jan
  2. Hello Jan!

使用curl工具,我们连接到myfirstejb Web 应用的Greet servlet,并向其传递参数。 Web 应用以问候语响应。

  1. $ curl localhost:8080/myfirstejb/
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <title>Test page</title>
  6. <meta charset="UTF-8">
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  8. </head>
  9. <body>
  10. <p>Test page</p>
  11. </body>
  12. </html>

访问根页面,应用将返回 HTML 测试页面。

使用实体 bean 持久化数据

在第二个示例中,我们创建一个将读取和保存汽车的 Web 应用。 汽车对象将保存在 Derby 数据库中。

我们使用car-app名称创建一个新的 Java Web 应用。 然后,我们创建一个新的Car实体。 实体类文件类型位于持久性类别中。 包将为com.zetcode.persistence。 主键类型为Long,并选中了创建持久性单元选项。

在下一页中,我们将持久性单元名称更改为carpu,然后选择默认的EclipseLink持久性供应器。 我们选择jdbc/sample数据源,并选择了Create表生成策略。 jdbc/sample数据源是指默认情况下位于用户主目录的.netbeans-derby子目录中的sample数据库。

EJB 简介 - 图5

图:持久性供应器

在此视图中,我们提供了持久性单元名称,持久性供应器,数据源和表生成策略。

实体 Bean

实体 Bean 是一种 Enterprise JavaBean,它表示持久存储中存在的业务实体对象。 实体 bean 由主键标识。 与在客户端会话的生存期内生存的会话 Bean 不同,实体 Bean 即使在 EJB 容器崩溃时也可以幸免。

Car.java

  1. package com.zetcode.persistence;
  2. import java.io.Serializable;
  3. import javax.persistence.Column;
  4. import javax.persistence.Entity;
  5. import javax.persistence.GeneratedValue;
  6. import javax.persistence.GenerationType;
  7. import javax.persistence.Id;
  8. import javax.persistence.Table;
  9. @Entity
  10. @Table(name="Cars")
  11. public class Car implements Serializable {
  12. private static final long serialVersionUID = 1L;
  13. @Id
  14. @GeneratedValue(strategy = GenerationType.AUTO)
  15. @Column(name="Id")
  16. private Long id;
  17. @Column(name="Name")
  18. private String name;
  19. @Column(name="Price")
  20. private int price;
  21. public Car() { }
  22. public Car(String name, int price) {
  23. this.name = name;
  24. this.price = price;
  25. }
  26. public String getName() {
  27. return name;
  28. }
  29. public void setName(String name) {
  30. this.name = name;
  31. }
  32. public int getPrice() {
  33. return price;
  34. }
  35. public void setPrice(int price) {
  36. this.price = price;
  37. }
  38. public Long getId() {
  39. return id;
  40. }
  41. public void setId(Long id) {
  42. this.id = id;
  43. }
  44. }

Car是 EJB 实体 Bean。 它是要存储在 Derby 数据库中的业务对象。

  1. @Entity
  2. @Table(name="Cars")
  3. public class Car implements Serializable {

实体 bean 用@Entity注解修饰。 该实体映射到Cars表。

  1. @Id
  2. @GeneratedValue(strategy = GenerationType.AUTO)
  3. @Column(name="Id")
  4. private Long id;

每个实体都有一个唯一的对象标识符。 此唯一标识符或主键使客户端能够定位特定的实体实例。 @Id声明此实体 bean 的标识符属性,@GeneratedValue注解用于指定主键的生成方式,@Column将标识符映射到数据库表的Id列。

  1. public Car() { }

持久性框架需要无参数的构造器。

EJB

我们创建一个本地无状态ManageCarBean企业 bean。 这次 EJB 具有本地接口视图。

ManageCarBeanLocal.java

  1. package com.zetcode.ejb;
  2. import javax.ejb.Local;
  3. import com.zetcode.persistence.Car;
  4. @Local
  5. public interface ManageCarBeanLocal {
  6. void saveCar(Car car);
  7. void setPrice(int price);
  8. void setName(String name);
  9. Car getCar(Long id);
  10. }

该接口定义了 EJB 客户端要使用的方法。 客户端只能通过 bean 的业务接口中定义的方法来访问会话 bean。

  1. @Local
  2. public interface ManageCarBeanLocal {

@Local装饰指定该接口是本地业务接口。

ManageCarBean.java

  1. package com.zetcode.ejb;
  2. import javax.ejb.Stateless;
  3. import javax.persistence.EntityManager;
  4. import javax.persistence.PersistenceContext;
  5. import com.zetcode.persistence.Car;
  6. @Stateless
  7. public class ManageCarBean implements ManageCarBeanLocal {
  8. private String name;
  9. private int price;
  10. @PersistenceContext(unitName = "carpu")
  11. private EntityManager em;
  12. public String getName() {
  13. return name;
  14. }
  15. @Override
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public int getPrice() {
  20. return price;
  21. }
  22. @Override
  23. public void setPrice(int price) {
  24. this.price = price;
  25. }
  26. @Override
  27. public void saveCar(Car car) {
  28. em.persist(car);
  29. }
  30. @Override
  31. public Car getCar(Long id) {
  32. Car car = em.find(Car.class, id);
  33. return car;
  34. }
  35. }

ManageCarBean读取并保存汽车对象。

  1. @PersistenceContext(unitName = "carpu")
  2. private EntityManager em;

容器使用persistence.xml中的信息创建EntityManager@PersistenceContext注解将实体管理器注入到 Bean 中。 管理器已映射到carpu持久性单元。 实体管理器用于通过持久性上下文与数据进行交互。

  1. @Override
  2. public void saveCar(Car car) {
  3. em.persist(car);
  4. }

saveCar()方法将汽车对象保存到数据库中; 在我们的例子中是 Derby。

  1. @Override
  2. public Car getCar(Long id) {
  3. Car car = em.find(Car.class, id);
  4. return car;
  5. }

getCar()方法通过其 ID 查找汽车。

persistence.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  3. <persistence-unit name="carpu" transaction-type="JTA">
  4. <jta-data-source>jdbc/sample</jta-data-source>
  5. <exclude-unlisted-classes>false</exclude-unlisted-classes>
  6. <properties>
  7. <property name="eclipselink.ddl-generation" value="create-tables" />
  8. </properties>
  9. </persistence-unit>
  10. </persistence>

persistence.xml文件是一个配置文件,其中包含有关我们在应用中使用的数据库的信息。 jdbc/sample是 GlassFish 服务器随附的内置数据源。 在我们的应用中,我们将数据保存在 Derby 的预先创建的sample数据库中。 如果eclipselink.ddl-generation属性不存在,则会自动导致创建Cars表。

EJB 简介 - 图6

图:NetBeans Derby 工具

我们可以使用 NetBeans Derby 工具来连接和管理数据库中的数据。 该工具位于“服务”窗口中。

servlet

我们创建两个 servlet:SaveCarReadCar。 我们将它们放入com.zetcode.web包中。 Servlet 是从 NetBeans Web 类别创建的。 两个 servlet 均以纯文本形式响应。

EJB 简介 - 图7

图:Apache Common Lang JAR

我们还包括用于帮助程序方法的 Apache Common Lang JAR。 可以从项目网站下载该库。

ValidateParameter.java

  1. package com.zetcode.util;
  2. import org.apache.commons.lang3.math.NumberUtils;
  3. public class ValidateParameter {
  4. private static final int MAX_PRICE_CAR = 10_000_000;
  5. public static boolean validateName(String param) {
  6. return !(null == param || "".equals(param) ||
  7. NumberUtils.isNumber(param));
  8. }
  9. public static boolean validateId(String param) {
  10. return !(null == param || "".equals(param) ||
  11. !NumberUtils.isNumber(param));
  12. }
  13. public static boolean validatePrice(String param) {
  14. if (null == param || "".equals(param) || !NumberUtils.isNumber(param)) {
  15. return false;
  16. }
  17. int price = Integer.valueOf(param);
  18. return !(price < 0 || price > MAX_PRICE_CAR);
  19. }
  20. }

ValidateParameter类用于验证请求参数。 参数不能为null或为空,并且 ID 和价格值必须为数字。 另外,价格必须在合理范围内。 我们使用 Apache Common Lang 的NumberUtils.isNumber()检查数字值。

SaveCar.java

  1. package com.zetcode.web;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.ejb.EJB;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.annotation.WebServlet;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import com.zetcode.ejb.ManageCarBeanLocal;
  11. import com.zetcode.persistence.Car;
  12. import com.zetcode.util.ValidateParameter;
  13. @WebServlet(name = "SaveCar", urlPatterns = {"/save"})
  14. public class SaveCar extends HttpServlet {
  15. @EJB
  16. private ManageCarBeanLocal manageCarBean;
  17. @Override
  18. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  19. throws ServletException, IOException {
  20. String sname = request.getParameter("name");
  21. String sprice = request.getParameter("price");
  22. String message;
  23. if (ValidateParameter.validateName(sname)
  24. && ValidateParameter.validatePrice(sprice)) {
  25. message = String.format("%s car is saved", sname);
  26. int price = Integer.valueOf(sprice);
  27. Car car = new Car(sname, price);
  28. manageCarBean.saveCar(car);
  29. } else {
  30. message = "Wrong parameters";
  31. }
  32. response.setContentType("text/plain;charset=UTF-8");
  33. try (PrintWriter out = response.getWriter()) {
  34. out.println(message);
  35. }
  36. }
  37. }

SaveCar Servlet 的目的是调用适当的 EJB 来保存汽车。 汽车对象的数据是从客户端发送的 URL 中读取的。

  1. @WebServlet(name = "SaveCar", urlPatterns = {"/save"})

@WebServlet注解将SaveCar Servlet 映射到/save路径。

  1. @EJB
  2. private ManageCarBeanLocal manageCarBean;

ManageCarBeanLocal企业 bean 被注入到 servlet 中。

  1. String sname = request.getParameter("name");
  2. String sprice = request.getParameter("price");

从请求中读取参数。

  1. if (ValidateParameter.validateName(sname)
  2. && ValidateParameter.validatePrice(sprice)) {

参数正在验证中。

  1. Car car = new Car(sname, price);
  2. manageCarBean.saveCar(car);

创建一个新的汽车对象并将其保存到数据库。 为了保存汽车对象,我们利用了ManageCarBeansaveCar()方法。

ReadCar.java

  1. package com.zetcode.web;
  2. import com.zetcode.ejb.ManageCarBeanLocal;
  3. import java.io.IOException;
  4. import java.io.PrintWriter;
  5. import javax.ejb.EJB;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.annotation.WebServlet;
  8. import javax.servlet.http.HttpServlet;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11. import com.zetcode.persistence.Car;
  12. import com.zetcode.util.ValidateParameter;
  13. @WebServlet(name = "ReadCar", urlPatterns = {"/read"})
  14. public class ReadCar extends HttpServlet {
  15. @EJB
  16. private ManageCarBeanLocal manageCarBean;
  17. @Override
  18. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  19. throws ServletException, IOException {
  20. response.setContentType("text/plain;charset=UTF-8");
  21. String message;
  22. String pid = request.getParameter("id");
  23. if (ValidateParameter.validateId(pid)) {
  24. Long carId = Long.valueOf(pid);
  25. Car rcar = manageCarBean.getCar(carId);
  26. if (null != rcar) {
  27. message = String.format("Name: %s, Price: %d",
  28. rcar.getName(), rcar.getPrice());
  29. } else {
  30. message = "Cannot find car with this ID";
  31. }
  32. } else {
  33. message = "Wrong parameters";
  34. }
  35. try (PrintWriter out = response.getWriter()) {
  36. out.println(message);
  37. }
  38. }
  39. }

ReadCar servlet 调用ManageCarBean企业 bean 从数据库中读取数据; 它根据提供的 ID 选择汽车对象。

  1. String sid = request.getParameter("id");

从 URL 读取 ID。

  1. Long carId = Long.valueOf(pid);
  2. Car rcar = manageCarBean.getCar(carId);
  3. if (null != rcar) {
  4. message = String.format("Name: %s, Price: %d",
  5. rcar.getName(), rcar.getPrice());
  6. } else {
  7. message = "Cannot find car with this ID";
  8. }

ManageCarBeanreadCar()方法用于检索汽车对象。

web.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  5. version="3.1">
  6. <session-config>
  7. <session-timeout>
  8. 30
  9. </session-timeout>
  10. </session-config>
  11. <error-page>
  12. <error-code>404</error-code>
  13. <location>/error404.txt</location>
  14. </error-page>
  15. <error-page>
  16. <location>/error.txt</location>
  17. </error-page>
  18. </web-app>

web.xml文件中,我们提供了两个错误页面。 error.txt是所有错误的默认错误页面,error404.txt是 404 错误的错误页面,当客户端请求不存在的资源时触发。 注意,error404.txt必须先于error.txt

EJB 简介 - 图8

图:错误页面s

我们将两个文本文件放置在网页中。

error.txt

  1. Error has occurred, check the GlassFish log file

这是一般错误页面。

error404.txt

  1. 404 : Page was not found

这是 404 错误的错误页面。

部署方式

是时候部署应用了。 通过右键单击 Web 项目并选择 Deploy 命令来部署应用。 请注意,当我们清理项目时,将取消部署该应用。 如果未运行所选的应用服务器,那么 deploy 命令还将启动它。

  1. $ ./asadmin list-applications
  2. MyFirstEJB <ejb, web>
  3. car-app <ejb, web>
  4. Command list-applications executed successfully.

GlassFish 的asadmin工具可用于确定当前已部署的应用。

GlassFish 启动时,NetBeans 会自动启动 Derby 服务器。 可以在 GlassFish 服务器设置中将其关闭。

EJB 简介 - 图9

图:GlassFish 服务器属性

在 NetBeans 的“服务”选项卡中,我们展开“服务器”节点,然后选择 GlassFish 属性。 在那里,我们可以看到“启动已注册 Derby 服务器”选项。

  1. $ curl localhost:8080/car-app/doread
  2. 404 : Page was not found

如果尝试访问不存在的资源,则会收到自定义 404 错误消息。

  1. $ curl "localhost:8080/car-app/save?name=Volvo&price=29000"
  2. Volvo car is saved

沃尔沃汽车将保存到数据库中。 注意 URL 的双引号的用法。

  1. $ curl "localhost:8080/car-app/save?name=Bentley&price=299000000"
  2. Wrong parameters

验证器发现了不切实际的高汽车价格。

  1. $ curl localhost:8080/car-app/read?id=401
  2. Name: Volvo, Price: 29000

我们从数据库中读取了一辆汽车。

使用 Maven 构建项目

NetBeans 在开发过程中为我们节省了许多繁琐的工作。 但是使用 Maven 手动构建项目是有益的。

  1. mvn archetype:generate -DgroupId=com.zetcode -DartifactId=car-app
  2. -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

我们创建一个新的 Maven 项目。 我们使用maven-archetype-webapp类型。

  1. $ tree
  2. .
  3. └── car-app
  4. ├── pom.xml
  5. └── src
  6. └── main
  7. ├── resources
  8. └── webapp
  9. ├── index.jsp
  10. └── WEB-INF
  11. └── web.xml
  12. 6 directories, 3 files

tree命令向我们显示了创建的项目结构。

  1. $ mkdir -p src/main/java/com/zetcode/ejb
  2. $ mkdir src/main/java/com/zetcode/persistence
  3. $ mkdir src/main/java/com/zetcode/web
  4. $ mkdir src/main/java/com/zetcode/util
  5. $ mkdir src/main/resources/META-INF

我们创建目录。

复制应用源文件后,项目结构如下所示:

  1. $ tree
  2. .
  3. ├── pom.xml
  4. └── src
  5. └── main
  6. ├── java
  7. └── com
  8. └── zetcode
  9. ├── ejb
  10. ├── ManageCarBean.java
  11. └── ManageCarBeanLocal.java
  12. ├── persistence
  13. └── Car.java
  14. ├── util
  15. └── ValidateParameter.java
  16. └── web
  17. ├── ReadCar.java
  18. └── SaveCar.java
  19. ├── resources
  20. └── META-INF
  21. └── persistence.xml
  22. └── webapp
  23. ├── index.jsp
  24. └── WEB-INF
  25. └── web.xml

不要忘记复制web.xml文件。 Maven 为我们创建了一个空的web.xml文件。

pom.xml

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.zetcode</groupId>
  5. <artifactId>car-app</artifactId>
  6. <packaging>war</packaging>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>car-app Maven Webapp</name>
  9. <url>http://maven.apache.org</url>
  10. <dependencies>
  11. <dependency>
  12. <groupId>org.eclipse.persistence</groupId>
  13. <artifactId>eclipselink</artifactId>
  14. <version>2.5.0</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.apache.commons</groupId>
  18. <artifactId>commons-lang3</artifactId>
  19. <version>3.0</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>javax</groupId>
  23. <artifactId>javaee-web-api</artifactId>
  24. <version>7.0</version>
  25. </dependency>
  26. </dependencies>
  27. <build>
  28. <plugins>
  29. <plugin>
  30. <groupId>org.apache.maven.plugins</groupId>
  31. <artifactId>maven-compiler-plugin</artifactId>
  32. <version>3.5.1</version>
  33. <configuration>
  34. <source>1.8</source>
  35. <target>1.8</target>
  36. </configuration>
  37. </plugin>
  38. </plugins>
  39. <resources>
  40. <resource>
  41. <directory>src/main/resources</directory>
  42. <filtering>true</filtering>
  43. </resource>
  44. </resources>
  45. <finalName>car-app</finalName>
  46. </build>
  47. </project>

pom.xml是一个文件,其中包含有关项目的信息以及 Maven 用于构建项目的配置详细信息。 我们提供了 Eclipse 链接持久性供应器,Apache Commons lang 库和 Java EE Web API 的依赖项。 我们指示 Maven 使用 Java8。最终的构建文件称为car-app.war,位于target子目录中。

  1. $ mvn package

该项目是使用mvn package命令构建的。

  1. $ ./asadmin start-domain

从 GlassFish 的bin目录中,启动 GlassFish 服务器。

  1. $ ./asadmin start-database --db-home ~/.netbeans-derby

Derby 服务器已启动。 NetBeans 在.netbeans-derby目录中创建 Derby 系统主目录,该目录位于用户的主目录中。 在这里,我们可以找到我们之前使用过的sample数据库。

  1. $ ~/bin/glassfish-4.1.1/glassfish/bin/asadmin deploy target/car-app.war

我们部署应用。 我们看到警告语Table/View 'CARS' already exists in Schema 'APP'。 这是eclipselink.ddl-generation属性的结果,该属性设置为create_tables。 我们可以忽略警告。

  1. $ curl localhost:8080/car-app/read?id=401
  2. Name: Volvo, Price: 29000

我们检索先前创建的汽车。

在本教程中,我们为一些简单的业务逻辑创建了 Enterprise JavaBeans。 我们已使用 NetBeans,Derby 和 Maven 作为示例。 ZetCode 具有以下相关教程: Derby 教程Java 教程Stripes 教程