用Java EE 5实现的网上书店实例(netbeans6.0)

本文章为转帖

作者:李力 (ada.li@sun.com)

2007/10/23

本教程介绍了如何使用NetBeans IDE 以及GlassFish 构建一个典型的Java EE 5应用实例. 该实例模拟网上书店, 主要实现的是对订单的管理。用户可以购买图书, 并修改订单. 该实例覆盖了Java DB, JPA(Java Persistence API), EJB 3.0, JSF等技术应用.

目录

第一部分:环境准备

    网上书店体系结构

    教程使用环境

    配置GlassFish

第二部分:数据准备

    创建数据库和表

    创建表

    配置JDBC资源

第三部分:实现JPA层与EJB层

    创建企业项目

    JPA层

    创建持久性单元

    创建实体类

    EJB层

    创建会话Bean

第四部分:实现Web层

    Web层

    创建Servlet

    测试

    JSF与Visual Web Pack

    创建Visual Web项目

    浏览商品

    查询订单

    生成订单

    删除订单

问题及解决

参考

网上商店说明

网上商店实现了商品浏览,用户可以进行订单查询,生成订单以及删除订单等操作。

教程使用环境

Java SE 5(或更高版本)

NetBeans IDE 6.0

GlassFish 或Sun Java Application Server PE 9.0 Update Release 1(或更高版本)

配置GlassFish

如果安装的 NetBeans IDE 与 GlassFish 捆绑在一起,则表明已在 IDE 中注册了应用服务器,不需要对其进行配置。如果单独下载并安装了 GlassFish或者Sun Java System Application Server 9.0,则必须为 IDE 配置可用的应用服务器。

配置单独安装的服务器:

    安装 NetBeans IDE 6.0和 GlassFish 后,启动 IDE。

    在“Services”窗口中,右键单击“Servers”节点,然后从弹出式菜单中选择“Add Servers…”。

    在“Add Server Instance”向导中,从“Server”栏目中选择 "GlassFish V2",然后单击“Next”。

    输入应用服务器的安装位置”Platform Location:”,选择“Register Local Default Domain”, 然后单击“Next”。

    缺省应用服务器域 domain1 的缺省用户名和口令如下:

    Admin Username:admin

    Admin Password:adminadmin

    请注意,如果在此处指定一个口令,则系统会将其存储在用户目录中,这可能会产生安全隐患。如果未在此处指定口令,则会在需要时提示您输入口令值。

    单击“Finish”。

创建数据库

在这节中使用GlassFish 捆绑的Derby数据库, 完成创建数据库,创建表,建立数据库连接池,建立数据库资源等。

创建Derby数据库

    启动 NetBeans IDE后,如果尚未启动数据库服务器,请选择菜单“Tools”>“Java DB Database”>“Start Server”。

    选择菜单“Tools”>“Java DB Database”>“Create Java DB Database”。

    在“Create Java DB Database”输入如下信息:

    Database Name:bookshop

    User Name:book

    Password: book

图一: 创建bookshop数据库

    NetBeans IDE会自动在”Services”>”Databases”节点下建立bookshop的数据库连接。

    图: bookshop数据库连接

    如果 bookshop 数据库的 jdbc 节点标记显示为连接中断 ,并且无法展开该节点,则表明 IDE 未连接到该数据库。要连接 bookshop 数据库,请右键单击 bookshop 数据库的 jdbc 节点, 选择“Connect…”。

    如果未出现bookshop的数据库连接, 在“Serivces”窗口中,右键单击“Databases”,然后从弹出式菜单中选择“New Connection…”以打开“New Database Connection”对话框。

从“Name”下拉列表中选择 "Java DB (Network)"。

在“Database URL”文本框中,键入” jdbc:derby://localhost:1527/bookshop”

将“User Name”设置为 book,将“Password”设置为 book,然后单击“确定”。

在建立连接后,请单击“确定”以关闭对话框。

图2: 新建bookshop数据库连接

创建表

到这一步, bookshop数据库是全新的,因此它是空的。现在,开始添加表和数据。NetBeans IDE可以使用表向导来逐个创建表, 这个教程里使用SQL脚本.

使用SQL脚本创建表

    右键单击bookshop 数据库下的表节点, 然后从弹出式菜单中选择”Execute Command”

    在新打开的”SQL Command 1”窗口中,输入以下SQL。

    代码样例 1:SQL

    create table "BOOK"."CUSTOMER"(        "CUSTOMER_ID" CHAR(12) not null primary key,        "CUSTOMER_NAME" VARCHAR(30),        "EMAIL" VARCHAR(40));insert into customer values ( 'ada', 'Ada Li', 'ada.li@sun.com');insert into customer values ( 'joey', 'Joey Shen', 'joey.shen@sun.com');insert into customer values ( 'michael', 'Michael Li', 'tao.li@sun.com');create table "BOOK"."PRODUCT"(        "PRODUCT_ID" INTEGER not null primary key,        "PRODUCT_NAME" VARCHAR(100),        "PURCHASE_COST" DECIMAL(12,2));insert into product values ( 1, 'Java(TM) EE 5 Tutorial', 34.64);insert into product values ( 2, 'Java EE 5 Development using Glassfish Application Server', 32.50);insert into product values ( 3, 'Enterprise JavaBeans 3.0', 31.49);insert into product values ( 4, 'Sun Certified Enterprise Architect for Java EE study Guide', 32.99);insert into product values ( 5, 'Java ME Game Programming', 49.99);create table "BOOK"."PURCHASE_ORDER"(        "ORDER_NUM" INTEGER not null primary key,        "CUSTOMER_ID" CHAR(12) not null,        "PRODUCT_ID" INTEGER not null,        "QUANTITY" SMALLINT);insert into PURCHASE_ORDER values ( 1, 'ada', 1, 1);insert into PURCHASE_ORDER values ( 2, 'ada', 5, 1);insert into PURCHASE_ORDER values ( 3, 'joey', 2, 2);

    点击”Run SQL”按钮(或者组合键 Ctrl+Shift+E), 运行成功的话,可以在bookshop 数据库连接的"Tables"节点,看到新生成三个表。

    CUSTOMER

    PRODUCT

    PURCHASE_ORDER

    右键单击表或列,然后从弹出式菜单中选择“View Data…”,可以查看表和列中的数据。

配置JDBC 连接池和JDBC资源

数据库连接池是服务器为特定的数据库提供的一组可重用的连接。请求数据库连接的应用程序将从该池中获取连接。当应用程序关闭某个连接后,该连接将会返回到连接池中。连接池属性可能随数据库供应商的不同而有所不同。一些公共属性包括数据库名称的 URL、用户名和口令等。

建立数据库连接池时,还将创建 JDBC 资源(也称为数据源)。JDBC 资源为应用程序提供了数据库连接。通常,应用程序所访问的每个数据库都至少有一个 JDBC 资源。一个数据库可以有多个 JDBC 资源。

下面介绍如何在GlassFish上配置 JDBC 连接池 和JDBC 资源

1.启动GlassFish, 在NetBeans IDE的”Services”窗口中的”Servers”节点下, 右键单击”GlassFish”, 选择”Start”

2.在浏览器地址窗口中,输入”http://localhost:4848”, 出现管理控制台登录界面. 缺省的管理员/密码: admin/adminadmin

配置 JDBC 连接池

接下来,将为bookshop数据库创建一个 JDBC 连接池,并定义数据库连接的特性。

    在管理控制台的左窗格中,展开“Resources”> "JDBC",然后选择“Connection Pools”。

    在“Connection Pools”页中,单击“New”以创建新的连接池。

    在“New JDBC Connection Pool”向导的第一步, 输入和选择如下内容。

    Name:bookshopPool

    Resource Type:javax.sql.DataSource

    Database Vendor:JavaDB点击"Next"按钮。

    在“New JDBC Connection Poo”向导的第二步,找到属性部分,修改以下属性值。

    DatabaseName: bookshop

    User: book

    Password: book

    ServerName:localhost

    PortNumber:1527

    属性设置完成后,点击同一页面”General”下的"ping"按钮,测试设置是否正确。如果正确,会显示"Ping Succeeded "的信息.

    点击"Save"按钮,在 GlassFish 中创建bookshopPool连接池.

配置 JDBC 资源

必须为bookshop创建一个 JDBC 资源,以便让部署后的应用程序能够通过它连接到bookshop数据库。

    在管理控制台的左窗格中,展开“Resources”> "JDBC" >“JDBC Resources”。

    单击“New”。用于创建新 JDBC 资源的页将出现在右窗格中, 输入或选择如下内容。

    JNDI Name:jdbc/bookshopDS

    Pool Name:bookshopPool

    点击"OK"按钮,在GlassFish中创建JDBC 资源 jdbc/bookshopDS.

创建企业项目

    NetBeans IDE中,选择“File”>“New Project”(Ctrl-Shift-N)。从 "Enterprise" 类别中选择“Enterprise Application”,然后单击“Next”。

    将项目命名为 BookshopApp,将服务器设置为 "GlassFish V2",将 Java EE 版本设置为 "Java EE 5",然后单击“Finish”。

    在NetBeans IDE的"Projects"窗口中,会出现三个项目

    BookshopApp

    BookshopApp-ejb

    BookshopApp-war

持久层

Java EE 5 平台引入了新的 Java 持久性 API(它是作为 JSR-220 的一部分开发的)。Java 持久性 API 不但可以在 EJB 组件外部使用(例如,在 Web 应用程序和应用程序客户端中使用),而且还可以在 Java EE 平台之外的 Java SE 应用程序中使用。

Java 持久性 API 具有以下主要功能:

实体是 POJO。与使用容器管理持久性 (Container-Managed Persistence, CMP) 的 EJB 组件不同,使用新 API 的实体对象不再是组件,并且它们不再需要位于 EJB 模块中。

标准化的对象关系映射。新规范将对对象关系映射的处理方式进行标准化,从而使开发者不再需要了解特定于供应商的策略。Java 持久性 API 使用标注来指定对象关系映射信息,但它仍支持 XML 描述符。

命名查询。现在命名查询是用元数据表示的静态查询。查询可以是 Java 持久性 API 查询或本地查询。这样会使重用查询变得非常简单。

简单的打包规则。由于实体 Bean 是简单的 Java 技术类,因此几乎可以在 Java EE 应用程序中的任意位置将其打包。例如,实体 Bean 可以是 EJB JAR、应用程序客户端 JARWEB-INF/libWEB-INF/classes 的一部分,甚至是企业应用程序归档 (Enterprise Application Archive, EAR) 文件中实用程序 JAR 的一部分。通过这些简单的打包规则,您不再需要创建 EAR 文件以使用来自 Web 应用程序或应用程序客户端的实体 Bean。

分离的实体。由于实体 Bean 是 POJO,因此可以对它们执行序列化,通过网络将其发送到其他地址空间,并在不识别持久性的环境中使用它们。这样,您就不再需要使用数据传输对象 (Data Transfer Object, DTO)。

EntityManager API。现在,应用程序编程人员可以使用标准 EntityManager API 来执行涉及实体的创建、读取、更新和删除 (Create Read Update Delete, CRUD) 操作。

IDE 提供了处理新 Java 持久性 API 的工具。您可以通过数据库自动生成实体类,或手动对实体类进行编码。IDE 还提供了用于创建和维护持久性单元的模板和图形编辑器。

创建持久性单元

持久性单元目的在于通知容器哪些实体类需要由实体管理器进行管理,以及这些实体需要使用哪些数据源信息。

    在“Projects”窗口中右键单击 "BookshopApp-ejb" 项目节点,然后选择“New”>“Other”以打开“New File”向导。

    从“Categories”栏目中,选择“Persistence”,”File Types”栏目中,选择“Persistence Unit ”, 然后单击“Next”。

    配置信息如下

Persistence Unit Name:BookshopApp-ejbPU

Persistence Provider: TopLink(缺省)

Data Source: jdbc/bookshopDS

Use Java Transaction APIs : Yes

Table Generation Strategy: None

    单击“完成”, 最后生成BookshopApp-ejb项目下生成persistence.xml, 这个文件中定义了持久性单元的属性

创建实体类

实体类用于表示要创建的关系数据库中的表。下面为bookshop数据库中的三张表创建实体类,实体类包括命名的查询标注、表示列的字段以及表示外键的关系。

    右键单击 "BookshopApp-ejb" 项目节点,然后选择“New”>“Other”以打开“New File”向导。

    从“Categories”栏目中,选择“Persistence”,”File Types”栏目中,选择“Entites from Classes ”, 然后单击“Next”。

    下一个窗口中, “Data Source”选择”jdbc/bookshopDS”, 点击”Add all”按钮, 将”Available Tables”中的三张表(CUSTOMER, PRODUCT, PURCHASE_ORDER)添加到”Selected Tables”中, 点击”Next”按钮。

    下一个窗口中,输入包名“bookshop.entities”,点击完成。

生成的Product实体类的部分代码如下:

代码样例 2:Product实体类

......@Entity@Table(name = "PRODUCT")@NamedQueries( {        @NamedQuery(name = "Product.findByProductId", query = "SELECT p FROM Product p WHERE p.productId = :productId"),        @NamedQuery(name = "Product.findByProductName", query = "SELECT p FROM Product p WHERE p.productName = :productName"),        @NamedQuery(name = "Product.findByPurchaseCost", query = "SELECT p FROM Product p WHERE p.purchaseCost = :purchaseCost")    })public class Product implements Serializable {    @Id    @Column(name = "PRODUCT_ID", nullable = false)    private Integer productId;    @Column(name = "PRODUCT_NAME")    private String productName;    @Column(name = "PURCHASE_COST")    private Long purchaseCost;......

实体类是一个简单的 Java 类。 @Entity 标注以将该类定义为实体类,其它标注的解释和说明可以查看相关文档。

EJB层

使用新的 EJB 3.0 API,可以减少并简化开发者需要完成的工作量,从而可以更轻松地进行软件开发。换句话说,就是使用了更少的类和代码。这是因为现在容器承担了更多的工作,从而实现了这一目的。下面是新 EJB 3.0 API 的一些功能和优点:

只需很少的类和接口。您不再需要 EJB 组件的 Home 接口和对象接口,因为现在容器负责公开必要的方法。您只需提供业务接口。您可以使用标注来声明 EJB 组件,并且通过容器来管理事务。

不再需要部署描述符。您可以在类中直接使用标注,为容器提供以前在部署描述符中定义的依赖关系和配置信息。如果没有任何特殊说明,容器将使用缺省规则来处理最常见的情况。

查找简单。您可以通过 EJBContext 直接在类中查找 JNDI 名称空间中的对象。

简化了对象关系映射。新的 Java 持久性 API 允许您使用 POJO 中的标注将 Java 对象映射到关系数据库,从而使对象关系映射变得更简单透明。

在 IDE 中,您可以对 Enterprise Beans 进行编码,就像对其他 Java 类进行编码一样,方法是:使用代码完成和编辑器提示实现正确的方法并使类与其接口保持同步。您不必使用特殊命令和对话框生成诸如业务方法或 Web 服务操作之类的内容,虽然这些命令仍可以帮助您熟悉 Java EE 5 代码的语法。

创建会话Bean

为 Product实体类创建一个会话Bean

    右键单击 EJB 模块,然后选择“New”>“Other”以打开“New File”向导。

    从“Categories”栏目中,选择“Persistence”,”File Types”栏目中,选择“Session beans for entities”, 然后单击“Next”。

    从”Available Entity Classes”列表中,选择 "bookshop.entities.Product"和"bookshop.entities.PurchaseOrder",单击“Add”,然后单击“Next”。

    包名设置为“bookshop.ejb”, “Create Interfaces”选择“Local“。

    单击“Finish”。

单击“Finish”后,将创建会话Bean 类和接口

ProductFacade.java

ProductFacadeLocal.java

PurchaseOrderFacade.java

PurchaseOrderFacadeLocal.java

ProductFacade.java代码如下。

代码样例 3:ProductFacade类

package bookshop.ejb;import bookshop.entities.Product;import java.util.List;import javax.ejb.Stateless;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;/** * * @author Sun */@Statelesspublic class ProductFacade implements ProductFacadeLocal {    @PersistenceContext    private EntityManager em;        /** Creates a new instance of ProductFacade */    public ProductFacade() {    }    public void create(Product product) {        em.persist(product);    }    public void edit(Product product) {        em.merge(product);    }    public void destroy(Product product) {        em.merge(product);        em.remove(product);    }    public Product find(Object pk) {        return (Product) em.find(Product.class, pk);    }    public List findAll() {        return em.createQuery("select object(o) from Product as o").getResultList();    }    }

其中,标注 @Stateless 用于将类声明为无态会话 Bean 组件。标注@PersistenceContext表明,PersistenceContext 资源已直接注入到会话 Bean 组件中。

Web层

Web层实现方式很多,这个教程里给出三种方式。一种是简单的Servlet,来显示Product信息, 另外一种是使用Visual Web JSF Page,实现对订单的查询,添加和删除,第三种是采用jMaki中的AJAX组件Data Table来显示Product信息。

创建Servlet

    在“Project”窗口中,右键单击 BookshopApp-war 节点,然后选择“New”>“Other”>”Web”-> "Servlet", 点击“Next”。

    类名:ProductServlet,包名:bookshop.web。单击“Next”。

    在下一个“Configure Servlet Deployment”窗口中,单击“Finish”按钮。

    ProductServlet 源代码编辑器中, 任意位置单击鼠标右键,选择“Enterprise Resource”>“Call Enterprise Bean”

    在“Call Enterprise Bean”窗口中,选择“BookshopApp-ejb” -> “ProductFacade”,点击完成。

    这一步骤之后,IDE会在 ProductServlet.java代码中,插入语句“@EJB private ProductFacadeLocal productFacade;”,表示对EJB的声明和引用。

    修改后的 ProductServlet.java代码如下:

代码样例 4:ProductServlet.java

......public class ProductServlet extends HttpServlet {    @EJB    private ProductFacadeLocal productFacade;        protected void processRequest(HttpServletRequest request, HttpServletResponse response)    throws ServletException, IOException {        response.setContentType("text/html;charset=UTF-8");        PrintWriter out = response.getWriter();                out.println("<html>");        out.println("<head>");        out.println("<title>ProductServlet</title>");        out.println("</head>");        out.println("<body>");                java.util.List list = productFacade.findAll();        java.util.Iterator products = list.iterator();        while (products.hasNext()){             bookshop.entities.Product obj = (bookshop.entities.Product) products.next();            out.println("<h3>Book " + obj.getProductId()                     + " | " + obj.getProductName()                     + " | " + obj.getPurchaseCost()                     +  "</h3>");        };                out.println("</body>");        out.println("</html>");        out.close();    }......

部署及运行企业应用程序

部署BookshopApp

    在“Project”窗口中,右键单击BookshopApp项目, 并选择“Undeploy and Deploy”

    成功部署后,可以在"Services"->"Server"->"GlassFish V2"->"Applications"->"Enterprise Applications"下,看到"BookshopApp"及子模块

运行BookshopApp

在“Project”窗口中,右键单击 BookshopApp项目, 并选择“Run”。 IDE 会执行以下所有任务:

生成企业应用程序项目及其所有子项目(Web 模块项目和 EJB 模块项目)。

如果服务器尚未运行,启动它。

如果企业应用程序已部署到应用服务器上,卸下它。

将企业应用程序部署到应用服务器上。

打开在指定的相对 URL 中的 Web 模块。

浏览器中自动打开的URL是"http://localhost:8080/BookshopApp-war/",显示空白的index.jsp, 修改URL为"http://localhost:8080/BookshopApp-war/ProductServlet",运行结果如下:

JSF (Jave Server Faces)

JSF(Java Server Faces)是Web应用程序的一种MVC框架.Visual Web JSF Page 是可视化的JSF页面和组件。

下面介绍了使用NetBeans Visual Web JSF Page开发网上商店的Web层,实现如下功能.

浏览商品

根据用户名查询对应订单

生成订单

删除订单

浏览商品

之前用Servlet实现了浏览商品的功能,接下来在Page1.jsp页面上利用JSF组件实现同样功能.

新建Visual Web JSF Page

    右键单击BookShopApp-war项目,选择””Visual Web JSP page

    在”New Visual Web Page“窗口中,输入

File Name: Page1.jsp

Default Java Package: bookshop.web

    点击”“Finish按钮。在bookShopApp-war项目中生成了两个文件

web pages/Page1.jsp JSF UI component

Source packages/bookshop.web/Page1.java (JSF Managed Bean

如果是在项目中第一次生成Visual Web JSF Page, 那么NetBeans还自动为项目导入”“Visual Web JavaServer Faces”框架。除在项目中添加了相关库之外,在项目的””Source Packages”下也自动生成如下Java类, 这些类用于保存不同作用范围的参数和变量:

ApplicationBean1.java

SessionBean1.java

RequestBean1.java

将组件添加到Web页面

    通过将组件从“Palette”窗口拖放到可视设计器中的Web 页上,如“Static Text”、“Button”、“Drop Down List”、“Table” 都属于组件面板的“Basic”类别.

    更改这些组件的属性对其进行了定制。

配置下拉列表组件(Drop Down List)

    打开“Services”窗口,展开“Databases”节点并检查是否已连接 bookshop 数据库。

    展开 bookshop 数据库的 jdbc 节点,然后展开“Table”节点。

    将 "CUSTOMER" 节点拖动到可视设计器的”Drop Down List”上。

    拖动成功的话,下拉列表会显示"abc"内容,“Navigator”窗口的 "Page1" 部分中将显示 "CustomerDataProvider" 节点,"SessionBean1" 部分中将显示 "CustomerRowSet" 节点。

    Page1.jsp的”Design“页面上,右键单击“Drop Down List”组件,然后从弹出式菜单中选择“Bind to Data”。

    在"Bind to Data"窗口,"Value Field"选择"CUSTOMER.CUSTOMER_ID","Display field"选择"CUSTOMER.CUSTOMER_NAME",点击"OK"按钮.

配置表组件(Table

    将 "bookshop" 数据库节点 >“Table”> "PRODUCT" 节点从“Services”窗口拖放到Page1.jsp 的“Design”面板上的“Table”组件中。如果显示“Display Target”对话框,请确保选择 table1,然后单击“OK”。

    拖动成功的话,表的显示内容会改变,“Navigator”窗口的 "Page1" 部分中将显示 "ProductDataProvider" 节点,"SessionBean1" 部分中将显示 "ProductRowSet" 节点。

    右键单击该表,然后从弹出式菜单中选择“Table Layout”,在"Table Layout"对话框里修改Head text, Table Title等信息,并调整字段的显示顺序.。

测试

    右键单击BookshopApp项目,选择"Undeploy and Deploy".

    在浏览器中输入URL: “http://localhost:8080/BookshopApp-war/”,显示如下结果,Drop Down List中显示的是CUSTOMER数据表的内容,而"Book List"显示的是PRODUCT数据表的内容.

根据用户名查询订单

从下拉列表中选择用户,点击"Search"按钮,可以显示出该用户的订单内容。实现这个功能,分为以下几步:

    创建一个新页OrderList.jsp来显示查询结果

    从page1.jsp传递用户名到OrderList.jsp

    设置Page1.jsp到OrderList.jsp的导航

创建新页OrderList

    在“Project”窗口中,右键单击”BookshopApp-war”节点,然后选择“New”->“Visual Web JSF Page”

    文件名输入"OrderList",然后单击“Finish”,在web下创建OrderList.jsp文件.

    将"Static Text","Text Field"和"Table"三个组件从“Palette”窗口拖放到可视设计器中的OrderList 页上,修改相关属性 .

配置表

    将 "bookshop" 数据库节点 >“Table”> "PURCHASE_ORDER" 节点从“Services”窗口拖放到OrderList 页上可视设计器中的“Table”组件上。

    拖动成功的话,表的显示内容会改变,“Navigagor”窗口的 "OrderList1" 部分中将显示 "purchase_orderDataProvider" 节点,"SessionBean1" 部分中将显示 "perchase_orderRowSet" 节点。

    在“Navigator”窗口中,右键单击 "SessionBean1" 下的 "perchase_orderRowSet",然后从弹出式菜单中选择“Edit SQL Statment”这将打开 SQL 查询编辑器。

    将 "bookshop" 数据库节点>“Table”> "PRODUCT" 节点从“Services”窗口拖放到SQL 查询编辑器上面的窗口中.或者在SQL 查询编辑器上面的窗口中,右键单击,选择”Add Table”, 从“Select Table(s) to Add”中选择“BOOKS.PRODUCT”.

    这样做是希望联合两个表,以便在OrderList.jsp中显示更全的信息。

    在窗口中心附近的网格区域,选择"CUSTOMER_ID”行,在"Criteria"栏中输入"=?"(注意输入时,切换到英文状态), “Order”选择”1”. 取消"BOOK.PRODUCT.PRODUCT_ID"的显示.

    修改SQL语句,联合PURCHASE_ORDER和PRODUCT两个表,点击IDE菜单上的"Save"按钮

    代码样例 5: SQL 查询编辑器

    SELECT ALL BOOK.PURCHASE_ORDER.ORDER_NUM,                     BOOK.PURCHASE_ORDER.CUSTOMER_ID,                     BOOK.PURCHASE_ORDER.PRODUCT_ID,                     BOOK.PURCHASE_ORDER.QUANTITY,                     BOOK.PRODUCT.PRODUCT_NAME,                     BOOK.PRODUCT.PURCHASE_COST FROM BOOK.PURCHASE_ORDER, BOOK.PRODUCTWHERE BOOK.PURCHASE_ORDER.CUSTOMER_ID = ?          AND BOOK.PURCHASE_ORDER.PRODUCT_ID = BOOK.PRODUCT.PRODUCT_ID 

    打开OrderList.jsp可视设计器,右键单击表,然后从弹出式菜单中选择“Table Layout”,在"Table Layout"对话框里增加修改字段,以显示PRODUCT表中的一些信息.

传递参数

接下来的步骤需要把Page1.jsp中的用户名传给OrderList.jsp"perchase_orderRowSet"的SQL查询.

首先,确定利用RequestBean来传递参数,打开Page1.jsp页面,

    右键单击“Navigator”窗口中的 "RequestBean1" 节点,然后选择“Edit Java Source”。 保存并关闭该文件。

    代码样例6:RequestBean1.java

        private String customerId;        public String getCustomerId() {        return customerId;    }    public void setCustomerId(String customerId) {        this.customerId = customerId;    }

    打开Page1.jsp可视设计器,双击"Search"按钮,打开Page1.jsp源文件窗口,光标停留在" public String button1_action() "方法内,修改内容如下:.

    代码样例6: Page1.jsp

        public String button1_action() {        // TODO: Process the action. Return value is a navigation        // case name where null will return to the same page.        getRequestBean1().setCustomerId((String)dropDown1.getValue());        return "case1";    }

    打开OrderList.jsp的Java源代码窗口,找到"prerender()"方法,prerender()是在JSP页面显示前被调用,因此适合在这个方法内传入参数。另外,”Return”按钮的返回值修改为“Case1“,是为了下面的页面导航作准备。 OrderList.jsp修改内容如下:

代码样例 7: OrderList.jsp

    public void prerender() {        String customerId = getRequestBean1().getCustomerId();        if (customerId != null){            textField1.setText(customerId);            try {                getSessionBean1().getPurchase_orderRowSet().setString(1,customerId);                getPurchase_orderDataProvider().refresh();            } catch (java.sql.SQLException ex) {                ex.printStackTrace();            }        }    } ......

public String button1_action() {

// TODO: Process the action. Return value is a navigation

// case name where null will return to the same page.

return "case1";

}

指定页面导航

点击"BookshopApp-war"项目下的"Page1.jsp”, 右键盘点击设计面板任意位置,选择”Page Navigation”, 出现”Page Flow的设计面板。鼠标拖动来完成页面导航。这里的导航支持JavaServer Faces, JSP, 和HTML文件.

测试

    右键单击BookshopApp项目,选择"Undeploy and Deploy".

    在浏览器中输入URL: “http://localhost:8080/BookshopApp-war/”,选择用户名,点击"Search"按钮,可以看到如下页面:

生成订单

实现生成订单,分为两步:

    得到新订单的信息

    把新订单信息保存到数据库

PURCHASE_ORDER数据表里包括了订单信息,一共四个字段,ORDER_NUM, CUSTOMER_ID, PRODUCT_ID,以及QUANTITY. 在page1.jsp页面中,可以得到CUSTOMER_ID和PRODUCT_ID的信息,ORDER_NUM是表的主键, 通常加入新纪录时, 主键值为当前最大主键值加1. 接下来的步骤是如何获得最大ORDER_NUM和QUANTITY

取得最大ORDER_NUM

    打开Page1.jsp可视设计器。

    从“Services”窗口中选择“Databases”> "bookshop" >“Table”> "PURCHASE_ORDER" 表,然后将它拖动到“Navigator”窗口中的 "SessionBean1" 节点上。

    在打开的“添加新的数据提供器”对话框中, 单击“创建 SessionBean1/purchase_orderRowSet1”单选按钮,将数据提供器的名称更改为maxOrder,然后单击“确定”。RowSet

    在 SessionBean1 中创建 maxOrderDataProvider 和 maxOrderRowSet

    在“Navigator”窗口中,双击 "SessionBean1" > "maxOrderRowSet" 以打开查询编辑器。在源代码窗格(上数第三个窗格)中单击鼠标左键。删除此处现有的 SQL 查询,然后输入以下查询后,点击"保存":

    代码样例 8: maxOrderRowSet SQL

    SELECT MAX(BOOK.PURCHASE_ORDER.ORDER_NUM)+1 AS MAXORDERID FROM BOOK.PURCHASE_ORDER

    MAXORDERID值将作为新订单的ORDER_NUM。

在Page1.jsp中添加QUANTITY输入框

    打开Page1.jsp可视设计器。右键点击"Table",选择“Table Layout”

    在”Table Layout”对话框中, 单击“ Column”New”,添加两个新列到表中。

Column Details

QUANTITY输入框设置

" Order"按钮列设置

Header Text

Quantity

Footer Text

Component Type

Text Field

Button

Value Expression

text

Order

Horizontal Align

Right

Center

    修改一些组件的ID, 通过菜单”Windows” ->”Properites” 打开属性窗口.

JSP 组件

id

组件类型

PRODUCT_ID

stProductId

Static Text

QUANTITY

tfQuantity

Text Field

”Order”按钮

addOrder

Button

订单保存在数据库中

    在page1.jsp可视设计器中,双击"Order"按钮,以打开Java 编辑器。在Java 编辑器中,插入点将位于该按钮的addOrder_action()事件处理程序方法中。

    源代码编辑器中, 任意位置单击鼠标右键,选择“Enterprise Resource”>“Call Enterprise Bean”

    在“Call Enterprise Bean”窗口中,选择“BookshopApp-ejb” -> “PurchaseOrderFacade”,点击完成。

    这一步骤之后,IDE会在 Page1.java代码中,加入对EJB的引用方法。

@EJB private PurchaseOrderFacadeLocal purchaseOrderFacade;”

    修改 Page1.java代码中 方法addOrder_action()

代码样例 9: Page1.java 中addOrder_action()

import bookshop.ejb.PurchaseOrderFacadeLocal;import bookshop.entities.*;......        @EJB PurchaseOrderFacadeLocal purchaseOrderFacade;    public String addOrder_action() {        //Get max order number.        CachedRowSetDataProvider maxOrder = getSessionBean1().getMaxOrderDataProvider();        maxOrder.refresh();        //Get order fields and save the new order into database        PurchaseOrder order = new PurchaseOrder();        order.setOrderNum((Integer) maxOrder.getValue("MAXORDERID"));        order.setCustomerId((String)dropDown1.getValue());        order.setProductId((Integer)stProductId.getValue());        order.setQuantity(new Short((String)tfQuantity.getValue()));        purchaseOrderFacade.create(order);                //Pass the user name to next page        getRequestBean1().setCustomerId((String)dropDown1.getValue());                return "case1";    }

注意addOrder_action()返回的也是"case1",因此,这个按钮和"search"按钮共享同样的导航,即同样会跳转到OrderList.jsp页面.

测试

    右键单击BookshopApp项目,选择"Undeploy and Deploy".

    在浏览器中输入URL: “http://localhost:8080/BookshopApp-war/”,选择用户, 输入数量,点击”Order”按钮. 在下一个页面,能够看到新添加的订单信息.

删除订单

    打开OrderList.jsp可视设计器。右键点击"Table",打开“Table Layout”对话框。

    单击“Columns”New”按钮,添加一个新列到表中。在“Properties”窗口中,把“Delete”按钮的ID改为“delete”

Column Details

"Delete"按钮列设置

Header Text

Footer Text

Component Type

Button

Value Expression

Delete

Horizontal Align

Center

    OrderList.jsp可视设计器中,双击"Delete"按钮,以打开Java 编辑器。在Java 编辑器中,插入点将位于该按钮的delete_action()事件处理程序方法中。

代码样例 9: OrderList.java 中delete_action()

import com.sun.data.provider.RowKey;......        public String buttonDelete_action() {        // TODO: Process the action. Return value is a navigation        // case name where null will return to the same page.        try {            RowKey rk = tableRowGroup1.getRowKey();            if (rk != null) {                purchase_orderDataProvider.removeRow(rk);                purchase_orderDataProvider.commitChanges();                purchase_orderDataProvider.refresh();}        } catch (Exception ex) {            log("ErrorDescription", ex);            error(ex.getMessage());        }                return null;    }

测试

    右键单击BookshopApp项目,选择"Undeploy and Deploy".

    在浏览器中输入URL: “http://localhost:8080/BookshopApp-war/”,选择用户, 点击”Search”按钮.

    在下一个页面上,点击”Delete”按钮.

安装jMaki Plug-in

    NetBeans IDE中,菜单选择“Tools”>“Plugins”>”。

    在“Plugins”窗口中,选择“Download”Add Plugins”按钮,在浏览器中选择jMaki在NetBeans的Plugin下载文件“org-netbeans-modules-sun-jmaki.nbm”

    点击”install”按钮后,会出现“NetBeans IDE Installer”窗口,点击”Next”按钮。

    在下一个窗口中,选择“I accept the terms in all of the license agreements”,点击”Install”按钮。

    如果希望Plugin立刻生效,在最后一个窗口中选择“Restart IDE Now”, 点击”Finish”按钮。

    重新启动NetBeans IDE后,选择菜单“Window”->”Palette”, 可以看到组件面板中已经出现了jMaki

使用AJAX组件Data Table显示信息

    右键单击BookshopApp-war项目,选择"New"->”Servlet”

    在“New Servlet”窗口中,File Name:输入”ProductService”, package:bookshop.web, 点击“Finish”按钮

代码样例 9: ProductService.java

/* * To change this template, choose Tools | Templates * and open the template in the editor. */package book.web;import java.io.*;import java.net.*;import javax.servlet.*;import javax.servlet.http.*;import javax.ejb.EJB;import bookshop.ejb.*;import bookshop.entities.*;import java.util.List;/** * * @author Sun */public class ProductService extends HttpServlet {       /**     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.    * @param request servlet request    * @param response servlet response    */    @EJB private ProductFacadeLocal productFacade;    protected void processRequest(HttpServletRequest request, HttpServletResponse response)    throws ServletException, IOException {        response.setContentType("text/html;charset=UTF-8");        PrintWriter out = response.getWriter();        try {            List<Product> list = productFacade.findAll();            out.println("{columns : [" +                    "{ label : 'Book ID', id : 'productid'}," +                    "{ label :'Book Name', id : 'productname'}," +                    "{ label :'Book Price', id : 'purchasecost'}" +                    "],");            out.println("rows: [");            for (int i = 0; i < list.size(); i++) {                Product b = list.get(i);                out.print("{ id: '" + b.getProductId() + "', " +                        "productid: '" + b.getProductId() + "'," +                        "productname: '" + b.getProductName() + "'," +                        "purchasecost: '" + b.getPurchaseCost() + "'}");                if (i < list.size() - 1) {                    out.println(",");                } else {                    out.println();                }            }            out.println("] }");          } finally {             out.close();        }    } ......

    打开BookshopApp-war项目下的index.jsp.

    从”palette”窗口中拖“jMaki Yahoo Data Tabel”到index.jsp中,拖动的结果会在项目下的Web Pages/resource下创建yahoo目录,包含Data Table所需要的一些image, html, js, css, json文件。

    修改index.jsp的内容.

代码样例 9: index.jsp

<%@ taglib prefix="a" uri="http://jmaki/v1.0/jsp" %><%--     Document   : index    Created on : 2007-11-26, 18:59:58    Author     : Sun--%><%@page contentType="text/html" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"   "http://www.w3.org/TR/html4/loose.dtd"><html>    <head>        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">        <title>JSP Page</title>    </head>    <body>        <h2>Hello World!</h2>        <a:widget name="yahoo.dataTable" service="/ProductService" />             </body></html>

6. 修改BookshopApp-war项目下的web.xml, 设置起始页面为index.jsp

测试

    右键单击BookshopApp项目,选择"Undeploy and Deploy".

    在浏览器中输入URL: “http://localhost:8080/BookshopApp-war/”

参考

Http://www.netbeans.org

在你成功地把自己推销给别人之前,你必须百

用Java EE 5实现的网上书店实例(netbeans6.0)

相关文章:

你感兴趣的文章:

标签云: