J2EE - NetBeans, JSF, Persistence API
这篇文章是一个简单的教程,适合任何想学习 J2EE 基础知识的人。循序渐进地介绍如何在 NetBeans 中创建一个简单的企业应用程序。
这是 3 部分中的第一部分
这篇文章写于 Java Beans 组件模型仍很流行的时代。Spring 当时是另一种选择。如今,有许多不同的技术和最新技术可供选择,但这篇文章可以作为 Java Beans J2EE 开发的参考。
我大部分时间都花在 .NET 技术上,但我知道 J2EE 非常强大,是企业应用领域的首选技术,所以我决定学习一些 J2EE 的基础知识。您可以在此处下载源代码。源代码涵盖了本文的第 2 部分和第 3 部分。
这是一个简单的教程,介绍如何使用 Java Persistence API、JSF、NetBeans 和 Derby 数据库“构建简单的企业 Web 应用程序”。我们将创建一个允许管理“公司及其产品”的应用程序。
您需要什么(获取最新版本)
- NetBeans 6.7.1 + UML 工具。我使用 6.7.1 是因为它支持带有逆向工程和代码生成的 UML 建模工具。该包尚未移植到更新版本的 NetBeans。
- J2EE
- 应用服务器 - 我使用的是 GlassFish 2.1
- Derby 数据库(Java DB 是 SUN 的此开源数据库版本)
您可以下载已经包含所有内容的 NetBeans Bundle。请记住,它是在 6.7.1/GlassFish 2.1 版本上测试的,某些设置在更新版本上可能不起作用。
技术与推荐阅读
- Java Persistence API - 将帮助我们进行对象关系映射 - 它将 Java 对象转换为数据库表。
- 实体 Bean (Entity Bean) - 代表对象(公司、产品)及其字段(名称、描述),这些字段随后在数据表中表示为列。
- 会话 Bean (Session Bean) - 而是表示可以对实体 Bean 执行的所有操作(创建新产品、列出公司产品...)
- JSF - 用于加快 GUI 创建速度和简化的 Web 应用程序框架。我使用的是 1.2 版本,它构建在 JSP(用于构建动态 Web 应用程序的较低层技术)之上。
创建项目
在 NetBeans 中选择新建 -> 新建项目 -> Java EE -> Enterprise Application。稍后将要求您指定应用程序服务器,您可以在此处选择已安装的 GlassFish 实例。
在最后一个选项卡中,您可以为 EJB 和 Web 应用程序模块指定名称。这是因为 NetBeans 将创建两个模块。EJB 模块将负责您的“模型和控制”,Web 应用程序模块将负责“视图”。
如果您希望使用 NetBeans UML 工具来建模您的实体 Bean,请选择新建项目 -> UML -> Java-Platform Model -> 完成,然后您可以创建类图。
开始建模
首先,我们要创建实体 Bean - 代表将存储在数据库中的现实世界实体的对象。在我们的应用程序中有两个:Company 和 Product。这是我们要创建的类图。
从此图我们可以生成实体类。右键单击 UML 项目 -> 生成代码。您应该得到以下类。
public class Company {
private int id;
private String description;
private String name;
private List<product> products;
public Company () {
}
public int getId () {
return id;
}
public void setId (int val) {
id = val;
}
public String getName () {
return name;
}
public void setName (String val) {
name = val;
}
public List<product> getProducts() {
return products;
}
public void setProducts(List<product> products) {
this.products = products;
}
public String getDescription () {
return description;
}
public void setDescription (String val) {
this.description = val;
}
}
public class Product {
private int id;
private String description;
private String name;
public Product () {
}
public String getDescription () {
return description;
}
public void setDescription (String val) {
description = val;
}
public int getId () {
return id;
}
public void setId (int val) {
id = val;
}
public String getName () {
return name;
}
public void setName (String val) {
name = val;
}
}
您也可以编写类并使用逆向工程来获取类图。
从类创建实体 Bean
要将类转换为实体 Bean,您需要执行两个简单的步骤 - **添加注解并实现 Serializable 接口**。
public class Company implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="companyID",nullable=false)
private int id;
@Column(name="companyDescription")
private String description;
@Column(name="companyName")
private String name;
@ManyToMany
private List<product> products;
...and all the setters and getter...
}
这非常直观。类必须用 @Entity 进行注解,并且至少有一个 @Id 字段。然后,我们可以指定将在数据库中创建的列的名称,以及生成 ID 值的策略。
您会注意到 NetBeans 会出现一个灯泡提示,表明没有 Persistence Unit - 现在我们将创建一个。
创建持久化单元
持久化单元将为我们执行对象-关系映射。要创建一个,我们首先需要创建一个数据库。
在“服务”窗格中找到数据库 -> Java DB -> 创建数据库并指定所需详细信息。
现在我们有了数据库,我们可以创建持久化单元将用于连接到 DB 的数据库连接。
数据库 -> 新建连接。
现在返回并右键单击应用程序的 EJB 模块,然后选择新建 -> 持久化单元。
在继续处理会话 Bean 之前,我们将准备一个命名查询。命名查询是静态查询,稍后将编译为 SQL 并由持久化单元使用。我们将使用一个简单的查询来获取表中的所有公司。我们将查询放在类定义之上。
@Entity
@NamedQuery(
name="Company.getAllCompanies",
query="SELECT c FROM Company c"
)
public class Company implements Serializable {
}
现在您已经完成了持久化单元,您可以尝试部署项目。当然,到目前为止还没有创建任何功能,但在部署过程中,数据库应该为您创建。您可以在“服务”选项卡中查看生成的数据库。
会话 Bean
现在我们将创建会话 Bean,它将提供我们可以对实体 Bean 执行的方法和操作。
转到 Enterprise Beans -> 新建 -> Session Bean,然后指定包并保留标准设置。
您会注意到新创建的 Bean 实现了一个以“Local”结尾的接口。
现在我们将添加第一个方法,它将返回数据库中的所有公司。NetBeans 会告诉您如何执行此操作 - 右键菜单 -> 插入代码 -> 添加业务方法。
该方法将在接口中定义,并在实现中创建方法存根。现在您可以像这样编辑代码。
@Stateless
public class SalesSessionBean implements SalesSessionLocal {
@PersistenceContext
private EntityManager em;
public List<company> getAllCompanies() {
List<company> companies = em.createNamedQuery(
"Company.getAllCompanies").getResultList();
return companies;
}
}
请注意,我们定义了 EntityManager,它是一个管理持久化上下文的类。持久化上下文是管理您的实体的篮子(代表 Company、Product... 的对象)。EntityManager 管理的类是我们的实体 Bean。在方法中,您可以看到我们调用了之前创建的命名查询。
后端 Bean (Backing Beans)
现在我们将创建一个介于会话 Bean 和代表 GUI 的 JSP 站点之间的中间层 - 这个层是后端 Bean。后端 Bean 是一个 Java 类,它被管理并且可以从实际的 JSP 页面访问。在 Web 模块中创建一个新类(新建 -> Java Class),并将其命名为 SalesBack。现在是实现。
public class SalesBack {
@EJB
SalesSessionLocal ssl;
public List<company> getAllCompanies(){
return ssl.getAllCompanies();
}
}
您可以看到该类基本上引用了会话 Bean(请注意,您必须引用接口,而不是实际的实现)。然后在方法中,我们只是调用会话 Bean 的方法。由此看来,这个层似乎不是必需的,但实际上它非常有用,正如您稍后将看到的。
Faces 配置
为了能够在 JSP 页面中使用后端 Bean,您需要对 faces-config.xml 文件进行一些更改。打开文件并将以下内容添加到 faces-config 元素中。
<managed-bean>
<managed-bean-name>sales</managed-bean-name>
<managed-bean-class>sales.back.SalesBack</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
请务必检查后端 Bean 类(包括包名)。稍后您可以在 JSP 页面中将此后端 Bean 引用为“sales”。
JSF 页面
现在我们将展示 Java Server Faces 带来的优势/组件以及如何使用它们。首先,我们将创建一个简单的页面,仅显示数据库中存储的所有公司的表格。在 Web 模块上创建一个带有 JSF 的新 JSP 页面(新建 -> JSF JSP Page)。创建页面后,您可以看到它包含两个 @taglib 指令,引用 JSF 框架的 TAGS。
JSP 技术可以通过“自定义标签”进行扩展。当我们使用 taglib 指令注册前缀时,我们就引入了 JSF 框架附带的所有自定义标签。第一个带有“f”前缀的组名为“Core”,引用所有与渲染器无关的组件(例如,转换器、验证器)。第二个带有“h”前缀的组名为“HTML”,引入了 JSF 提供的所有 HTML 标签和组件,用于创建精美的 GUI 和功能性 GUI(按钮、表格、网格...)。
好的,现在让我们输入将显示公司表格的代码。
<h1><h:outputtext value="Companies List"></h:outputtext></h1> <h:datatable value="#{sales.allCompanies}" var="item"> <h:column> <f:facet name="header"><h:outputtext value="Name"></h:outputtext> <h:outputtext value="#{item.name}"> </h:outputtext> <h:column> <f:facet name="header"><h:outputtext value="Description"> </h:outputtext> <h:outputtext value="#{item.description}"> </h:outputtext> </f:facet> </h:column></f:facet></h:column></h:datatable>
JSF 的主要优势在于它允许我们将某些 HTML 组件的内容绑定到后端 Bean 中的属性/字段。因为在我们的后端 Bean 中有一个名为“getAllCompanies”的方法,所以在这里我们可以将该方法的返回值引用为“#{sales.allCompanies}”。这种绑定是在“value
属性来完成的。请注意,第二个属性 var
允许您为绑定集合的某一行设置“名称”。稍后在列定义中,您可以通过此名称(此处为“item”)来访问集合中的一个公司。
web.xml 中的 Faces Servlet 配置
好的,现在您已经创建了 JSP 文件,是时候尝试一下了。在此之前,您必须告诉应用程序服务器,当用户导航到您的页面时,该页面包含 Faces 元素,并且必须使用 Faces Servlet 进行处理。打开 web.xml 并按如下方式修改 Faces Servlet 设置。
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
重要的部分是映射配置。基本上,您是在说每个以 **jsf** 结尾的文件都将由 Faces Servlet 处理。现在,如果您创建的文件名为“companies.jsp”,那么在浏览器中,您将通过“companies.jsf”来引用它。现在运行项目,并在浏览器中输入“companies.jsf”的路径,您应该会看到以下结果。
显然,公司表格是空的。所以继续使用 NetBeans(服务 -> 数据库)运行一些 SQL INSERT 语句,您应该能够看到插入到您表格中的数据。
INSERT INTO SALES.COMPANY (companyname, companydescription) values('First company',
'Sales bananas');
INSERT INTO SALES.COMPANY (companyname, companydescription) values('Second company',
'Sales oranges');
在下一篇文章中,我将完成这个应用程序,并提供一些附加功能来编辑公司详细信息以及添加和删除公司的产品。