在本教程中,我们学习如何使用 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
。
Figure: Server and Settings
在此对话框中,我们选择应用服务器,Java EE 版本和上下文路径。
index.html
这是我们的index.html
页面。 如果我们访问应用的根页面,它将返回。
我们右键单击应用图标,然后选择一个 Session Bean 类型的新 EJB。 我们将 bean 称为MyFirstBean
,键入com.zetcode.ejb
包,然后选择无状态会话类型。
Figure: Creating a new session bean in NetBeans
无状态会话 Bean 不维护与客户端的对话状态。 当客户端调用无状态 Bean 的方法时,该 Bean 的实例变量可能包含特定于该客户端的状态,但仅在调用期间包含。 该方法完成后,客户端特定的状态将丢失。
FirstBean.java
MyFirstBean
是无状态会话 Bean。 使用@Stateless
装饰创建一个无状态会话 bean。 它具有no-interface view
,其中不使用本地业务接口,并且 Bean 类的所有公共方法都自动向调用者公开。
MyFirstBean's
的工作是构造对呼叫者的问候。
接下来,我们通过右键单击项目图标并从 Web 类别中选择 Servlet 文件类型来创建一个新的 Servlet。 我们将 servlet 称为Greet
,然后键入com.zetcode.web
包。 我们将 URL 模式更改为/greet
。
Figure: New servlet creation
在新的 Servlet 对话框中,我们提供 Servlet 名称及其包。
Greet.java
Greet
Servlet 从客户端发送的 URL 中读取名称参数,调用 EJB 的createMessage()
业务方法,并以纯文本形式返回响应。
@EJB
注解将 EJB 注入 Servlt。
servelt 响应以 UTF-8 字符集的纯文本格式显示。
我们从请求中检索name
参数,并将其设置为 EJB。
我们将其称为createMessage()
业务方法。
Figure: MyFirstEJB project structure
我们构建应用并将其部署到 GlassFish 服务器。 要构建应用,请右键单击项目图标,然后选择“ Build”(构建)。 要部署应用,请右键单击项目图标,然后选择“部署”。
使用curl
工具,我们连接到myfirstejb
Web 应用的Greet
servlet,并向其传递参数。 Web 应用以问候语响应。
访问根页面,应用将返回 HTML 测试页面。
使用实体 bean 持久化数据
在第二个示例中,我们创建一个将读取和保存汽车的 Web 应用。 汽车对象将保存在 Derby 数据库中。
我们使用car-app
名称创建一个新的 Java Web 应用。 然后,我们创建一个新的Car
实体。 实体类文件类型位于持久性类别中。 软件包将为com.zetcode.persistence
。 主键类型为Long
,并选中了创建持久性单元选项。
在下一页中,我们将持久性单元名称更改为carpu
,然后选择默认的EclipseLink
持久性提供程序。 我们选择jdbc/sample
数据源,并选择了Create
表生成策略。 jdbc/sample
数据源是指默认情况下位于用户主目录的.netbeans-derby
子目录中的sample
数据库。
Figure: Persistence provider
在此视图中,我们提供了持久性单元名称,持久性提供程序,数据源和表生成策略。
实体 Bean
实体 Bean 是一种 Enterprise JavaBean,它表示持久存储中存在的业务实体对象。 实体 bean 由主键标识。 与在客户端会话的生存期内生存的会话 Bean 不同,实体 Bean 即使在 EJB 容器崩溃时也可以幸免。
Car.java
Car
是 EJB 实体 Bean。 它是要存储在 Derby 数据库中的业务对象。
实体 bean 用@Entity
注释修饰。 该实体映射到Cars
表。
每个实体都有一个唯一的对象标识符。 此唯一标识符或主键使客户端能够定位特定的实体实例。 @Id
声明此实体 bean 的标识符属性,@GeneratedValue
注解用于指定主键的生成方式,@Column
将标识符映射到数据库表的Id
列。
持久性框架需要无参数的构造函数。
EJB
我们创建一个本地无状态ManageCarBean
企业 bean。 这次 EJB 具有本地接口视图。
ManageCarBeanLocal.java
该接口定义了 EJB 客户端要使用的方法。 客户端只能通过 bean 的业务接口中定义的方法来访问会话 bean。
@Local
装饰指定该接口是本地业务接口。
ManageCarBean.java
ManageCarBean
读取并保存汽车对象。
容器使用persistence.xml
中的信息创建EntityManager
。 @PersistenceContext
注释将实体管理器注入到 Bean 中。 管理器已映射到carpu
持久性单元。 实体管理器用于通过持久性上下文与数据进行交互。
saveCar()
方法将汽车对象保存到数据库中; 在我们的例子中是德比。
getCar()
方法通过其 ID 查找汽车。
persistence.xml
persistence.xml
文件是一个配置文件,其中包含有关我们在应用中使用的数据库的信息。 jdbc/sample
是 GlassFish 服务器随附的内置数据源。 在我们的应用中,我们将数据保存在 Derby 的预先创建的sample
数据库中。 如果eclipselink.ddl-generation
属性不存在,则会自动导致创建Cars
表。
Figure: NetBeans Derby tool
我们可以使用 NetBeans Derby 工具来连接和管理数据库中的数据。 该工具位于“服务”窗口中。
servlet
我们创建两个 servlet:SaveCar
和ReadCar
。 我们将它们放入com.zetcode.web
包中。 Servlet 是从 NetBeans Web 类别创建的。 两个 servlet 均以纯文本形式响应。
Figure: Apache Common Lang JARs
我们还包括用于帮助程序方法的 Apache Common Lang JAR。 可以从项目网站下载该库。
ValidateParameter.java
ValidateParameter
类用于验证请求参数。 参数不能为null
或为空,并且 ID 和价格值必须为数字。 另外,价格必须在合理范围内。 我们使用 Apache Common Lang 的NumberUtils.isNumber()
检查数字值。
SaveCar.java
SaveCar
Servlet 的目的是调用适当的 EJB 来保存汽车。 汽车对象的数据是从客户端发送的 URL 中读取的。
@WebServlet
注释将SaveCar
Servlet 映射到/save
路径。
ManageCarBeanLocal
企业 bean 被注入到 servlet 中。
从请求中读取参数。
参数正在验证中。
创建一个新的汽车对象并将其保存到数据库。 为了保存汽车对象,我们利用了ManageCarBean's
saveCar()
方法。
ReadCar.java
ReadCar
servlet 调用ManageCarBean
企业 bean 从数据库中读取数据; 它根据提供的 ID 选择汽车对象。
从 URL 读取 ID。
ManageCarBean's
readCar()
方法用于检索汽车对象。
web.xml
在web.xml
文件中,我们提供了两个错误页面。 error.txt
是所有错误的默认错误页面,error404.txt
是 404 错误的错误页面,当客户端请求不存在的资源时触发。 注意,error404.txt
必须先于error.txt
。
Figure: Error pages
我们将两个文本文件放置在网页中。
error.txt
这是一般错误页面。
error404.txt
这是 404 错误的错误页面。
部署方式
是时候部署应用了。 通过右键单击 Web 项目并选择 Deploy 命令来部署应用。 请注意,当我们清理项目时,将取消部署该应用。 如果未运行所选的应用服务器,那么 deploy 命令还将启动它。
GlassFish 的asadmin
工具可用于确定当前已部署的应用。
GlassFish 启动时,NetBeans 会自动启动 Derby 服务器。 可以在 GlassFish 服务器设置中将其关闭。
Figure: GlassFish server properties
在 NetBeans 的“服务”选项卡中,我们展开“服务器”节点,然后选择 GlassFish 属性。 在那里,我们可以看到“启动已注册 Derby 服务器”选项。
如果尝试访问不存在的资源,则会收到自定义 404 错误消息。
沃尔沃汽车将保存到数据库中。 注意 URL 的双引号的用法。
验证器发现了不切实际的高汽车价格。
我们从数据库中读取了一辆汽车。
使用 Maven 构建项目
NetBeans 在开发过程中为我们节省了许多繁琐的工作。 但是使用 Maven 手动构建项目是有益的。
我们创建一个新的 Maven 项目。 我们使用maven-archetype-webapp
类型。
tree
命令向我们显示了创建的项目结构。
我们创建目录。
复制应用源文件后,项目结构如下所示:
不要忘记复制web.xml
文件。 Maven 为我们创建了一个空的web.xml
文件。
pom.xml
pom.xml
是一个文件,其中包含有关项目的信息以及 Maven 用于构建项目的配置详细信息。 我们提供了 Eclipse 链接持久性提供程序,Apache Commons lang 库和 Java EE Web API 的依赖项。 我们指示 Maven 使用 Java8。最终的构建文件称为car-app.war
,位于target
子目录中。
该项目是使用mvn package
命令构建的。
从 GlassFish 的 bin 目录中,启动 GlassFish 服务器。
Derby 服务器已启动。 NetBeans 在.netbeans-derby
目录中创建 Derby 系统主目录,该目录位于用户的主目录中。 在这里,我们可以找到我们之前使用过的sample
数据库。
我们部署应用。 我们看到警告语Table/View 'CARS' already exists in Schema 'APP'
。 这是eclipselink.ddl-generation
属性的结果,该属性设置为create_tables
。 我们可以忽略警告。
我们检索先前创建的汽车。
在本教程中,我们为一些简单的业务逻辑创建了 Enterprise JavaBeans。 我们已使用 NetBeans,Derby 和 Maven 作为示例。