- Java EE項目應用開發
- 劉勇軍 王電鋼編著
- 5760字
- 2018-12-30 08:37:21
1.6 典型MVC框架Struts及其應用
隨著Java Web開發技術的不斷成熟,越來越多的開發人員開始使用Web應用框架,框架為Java Web應用提供了預備的軟件架構和相關的軟件包,它能夠大大提高開發Java Web應用的速度和效率。在眾多的Java Web開發框架中,最典型的、應用最為廣泛的莫過于Struts框架。
Struts框架是最早發布的基于MVC設計模式的Java Web框架,它是由Apache軟件組織提供的一項開源項目,尤其適用于開發大型可擴展的Java Web應用。Struts為Java Web應用提供了一個通用的框架,使得開發人員可以將精力集中在如何解決實際業務問題上。
下面簡單介紹一下Struts的基本框架。
1.6.1 Struts框架
Struts框架以ActionServlet作為核心控制器,整個應用由客戶端請求驅動。在Web應用啟動時加載并初始化核心控制器ActionServlet,它將從配置文件struts-config.xml中讀取配置信息,并將它們存放在各種配置對象中,如Action的映射信息存放在ActionMapping對象中。
當客戶端向Web應用發送請求時,由Struts的核心控制器ActionServlet攔截請求,檢索和用戶請求匹配的ActionMapping實例,如果該實例不存在,就返回用戶請求路徑無效的信息。接著創建一個與請求對應的ActionForm Bean對象,并把客戶提交的表單數據保存在其中,根據配置信息決定是否需要進行表單數據校驗以及屬性重新設置。然后根據ActionMapping實例包含的映射信息決定是否需要調用那個業務邏輯控制器(Action)處理用戶請求,通過Action調用業務邏輯模型組件中方法,更新模型數據狀態,并返回一個ActionForward對象,決定應用請求轉發流程,呈現給用戶JSP視圖。
在Struts框架中,控制器就是它的核心,Struts控制器由兩部分組成:核心控制器和業務邏輯控制器。其中核心控制器就是ActionServlet,由Struts框架提供;業務邏輯控制器就是用戶自定義的Action,由應用開發者提供。
Struts是典型的MVC框架,如圖1-40顯示了實現MVC的Struts框架流程。

圖1-40 Struts框架流程
● 視圖:就是一組JSP文件,在這些JSP文件中沒有業務邏輯,也沒有模型信息,只有標簽,這些標簽可以是標準的JSP標簽或客戶自定義標簽,也可以是Struts標簽庫中的標簽。通常情況下,ActionFrom Bean也是屬于視圖模塊,它被利用來進行視圖和控制器之間表單數據的傳遞:一方面Struts框架把用戶輸入的表單數據保存在ActionForm Bean中,把它傳遞給控制器;另一方面控制器可以對ActionForm Bean中的數據進行修改,JSP文件使用Struts標簽讀取修改后的ActionForm Bean的信息,重新設置HTML表單。
● 模型:表示應用程序的狀態和業務邏輯。主要由底層的業務邏輯組件充當,這些業務邏輯組件封裝了底層數據庫訪問、業務邏輯方法實現。對于企業級Java EE應用來說,模型不僅僅是簡單的JavaBean,可能是一個或多個EJB組件,也可能是一個WebService服務。Struts框架沒有為實現Model組件提供任何支持。
● 控制器:由ActionServlet類和Action類實現。ActionServlet是Struts框架中的核心組件,繼承了javax.servlet.http.HttpServlet類,是一個標準的Servlet,它在MVC模型中扮演中央控制器角色,該控制器負責攔截所有HTTP請求,然后根據用戶請求決定是否需要調用業務邏輯控制器,如果需要調用業務邏輯控制器,則將請求轉發給Action處理,否則直接轉向請求的JSP頁面。業務邏輯控制器負責處理用戶請求,但它本身并不具有處理業務邏輯能力,而是調用Model來完成處理。
1.6.2 Struts框架應用:電子商務網站—購物車應用
為了幫助獲得使用Struts開發Java Web應用的經驗,講解一個簡單的Struts應用例子——電子商務網站中的購物車應用實現。
1.分析電子商務網站—購物車應用需求
在開發應用時,首先從分析需求入手,列舉該應用的各種功能,以及限制條件。電子商務網站—購物車應用的需求比較簡單,其包括如下需求:
● 客戶瀏覽商品。
● 添加商品到購物車。
● 顯示購物車中商品數量。
● 客戶可能更新商品數量、刪除購物車中的商品。
● 客戶可以結賬。
購物車應用處理流程如圖1-41所示。

圖1-41 購物車應用處理流程
2.數據分析設計
通過分析電子商務網站中購物車應用需求,可以抽取購物車應用中所涉及的實體對象包括產品信息(cart_product)、產品類別(cart_category)、商品信息(cart_item)、商品庫存(cart_inventory)、商品供應商(cart_supplier)。產品信息與產品類別是一對多的關系,即某個產品類別下有多個產品;產品信息與商品信息時一對多的關系;商品信息與商品庫存是一對一的關系;商品信息與商品供應商存在一對多關系。如圖1-42所示是購物車應用中各數據實體關系圖。

圖1-42 購物車應用中各數據實體關系圖
仍然采用電子商務網站—用戶注冊登錄應用所構建數據,創建購物車應用相關數據表,創建數據表的sql語句如下。
● 商品供應商信息表:
create table eb_c_supplier ( supplierid char(10) not null, suppliername varchar(80), status char(2) not null, addr1 varchar(80), addr2 varchar(80), city varchar(80), state varchar(80), zip varchar(6), phone varchar(80), constraint pk_supplier primary key (supplierid) );
● 產品類別信息表:
create table eb_c_category ( cateid char(10) not null, name varchar(80), descn varchar(255), constraint pk_category primary key (cateid) );
● 產品信息表:
create table eb_c_product ( productid char(10) not null, cateid char(10) not null, name varchar(80) , descn varchar(255), constraint pk_product primary key (productid), constraint fk_product_1 foreign key (cateid) references eb_c_category (cateid) );
● 商品信息表:
create table eb_c_item ( itemid char(10) not null, productid char(10) not null, listprice float, unitcost float, supplierid char(10) not null, status varchar(2), attr1 varchar(80), attr2 varchar(80), attr3 varchar(80), attr4 varchar(80), attr5 varchar(80), constraint pk_item primary key (itemid), constraint fk_item_1 foreign key (productid) references eb_c_product (productid), constraint fk_item_2 foreign key (supplierid) references eb_c_supplier (supplierid) );
● 商品庫存表:
create table eb_c_inventory ( invenid char(10) not null, itemid char(10) not null, itemqty int not null, constraint pk_inventory primary key (invenid), constraint fk_inven_1 foreign key (itemid) references eb_c_item (itemid) );
3.運用Struts框架
將Struts框架運用于電子商務網站的購物車應用中。Struts框架可以方便迅速地把一個復雜的應用劃分為模型、視圖和控制器組件,而Struts的配置文件struts-config.xml則可以靈活地組裝這些組件,從而簡化開發過程。
在電子商務網站項目TopEBus中添加Struts框架支持:
● 加載jar包。
要想獲得Struts框架支持,必須下載Struts框架jar包,可以到http://struts.apache.org/下載Struts,下載后直接解壓縮到指定目錄,然后找到lib目錄,將其中的jar包添加TopEBus構建路徑中即可。
實際上這里只需要幾個jar包即可:antlr.jar,commons-beanutils.jar,commons-digester.jar, commons-fileupload.jar,commons-logging.jar,commons-validator.jar,jakarta-oro.jar,struts.jar。將這幾個jar包直接復制到TopEBus項目下WebRoot\WEB-INF\lib目錄下即可。
● 配置web.xml。
由于在項目中添加了Struts框架支持,所以需要在Web應用部署描述符web.xml文件中添加Struts配置,配置如【代碼1-15】所示。
【代碼1-15】 web.xml文件Struts配置片段。
<!-- 配置struts --> <servlet> <servlet-name>struts</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>struts</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
● 配置struts-config.xml。
Struts框架允許把應用劃分為多個組件,從而提高開發效率。而Struts框架的配置文件struts-config.xml可以把這些組件組裝起來,決定如何使用它們。這里僅僅只是添加struts-config.xml文件,暫時沒有在里面添加組件,如【代碼1-16】所示。
【代碼1-16】 struts-config.xml代碼片段。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation //DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> <!-- =========Form Bean Definitions=========================--> <form-beans> <!—這里配置視圖組件ActionForm Bean --></form-beans> <!--=========Action Mapping Definitions=============--> <action-mappings><!—這里配置控制器組件action --></action-mappings> <!-- ========Message Resource Definitions==============--> <message-resources parameter=" " /><!—這里配置資源文件 --> </struts-config>
4.構建模型組件
在購物車應用中,主要包含一些對應數據表構建的域對象、專門為購物車構建的域對象和對應域對象操作的數據訪問JavaBean對象。
數據表域對象包括有對應供應商信息的域對象EB_C_Supplier.java、對應產品信息的域對象EB_C_Product.java、對應產品種類信息的域對象EB_C_Category.java、對應商品項信息的域對象EB_C_Item.java、對應商品庫存信息的域對象EB_C_Inventory.java等,因這些是最簡單的POJO類,這里略去對應代碼。
專門為購物車構建的域對象包括EB_C_CartItem和EB_C_Cart。
其中EB_C_CartItem域對象描述的是購物車中每一項商品(EB_C_Item),包括有該項商品的相關信息、數量以及總價格。此外,定義calculateTotal()方法用于計算該域對象內所有商品的總金額(單價*數量),當然,在設置EB_C_Item的數量時,需要計算總價格,這樣才能保持數據一致。其詳情如【代碼1-17】所示。
【代碼1-17】 EB_C_CartItem.java文件。
public class EB_C_CartItem { private EB_C_Item item; // 私有字段 private int quantity; private BigDecimal total; public EB_C_Item getItem() {return item;} // JavaBeans方法 public int getQuantity() {return quantity;} public BigDecimal getTotal() {return total;} private void calculateTotal() {// 計算總價格 if (item != null && item.getListprice() != 0.0f) { total=new BigDecimal(item.getListprice()).multiply(new BigDecimal (quantity)); } else {total = null;} } public void setItem(EB_C_Item item) {// 設置Item,同時計算總價格 this.item = item; calculateTotal(); } public void setQuantity(int quantity) {// 設置數量,同時計算總價格 this.quantity = quantity; calculateTotal(); } public void incrementQuantity(){//增加Item數量,同時計算總價格 quantity++; calculateTotal(); } }
EB_C_Cart代表了購物車域對象,購物車用來保存客戶所選擇的商品,其中提供了添加商品、修改商品數量、刪除購物車中商品、查看購物車中商品總金額等方法。在增加EB_C_Item到EB_C_CartItem中后,需要調用cartItem.incrementQuantity()方法使EB_C_Item數量加1,當然也可以使用cartItem.setQuantity(1)方法使cartItem的初始數量為1。計算購物車中所有物品總金額的方法為getSubTotal(),需要注意的是,BigDecimal是一個對象,所以不能直接調用:subTotal=subtotal+listprice*quantity之類的方法,BigDecimal為數據運算提供一系列方法,例如, add(BigDecimal val)表示加;subtract(BigDecimal val)表示減;multiply(BigDecimal val)表示乘;divide(BigDecimal val,int roundingMode)表示除。其詳情如【代碼1-18】所示。
【代碼1-18】 EB_C_Cart.java文件。
public class EB_C_Cart { /** 購物車中所有的商品信息都保存在Map中* */ private final Map<String, EB_C_CartItem> itemMap = Collections .synchronizedMap(new HashMap<String, EB_C_CartItem>()); public Iterator<EB_C_CartItem>getCartItems(){/** 獲得所有cartItem**/ return itemMap.values().iterator(); } public int getNumberOfItems() {/** 獲得EB_C_Item的總數* */ return itemMap.size(); } public boolean containsItemId(String itemId) {/**是否包含某個EB_C_Item* */ return itemMap.containsKey(itemId); } public void addItem(EB_C_Item item) {/** 增加EB_C_Item* */ EB_C_CartItem cartItem = itemMap.get(item.getItemid()); if (cartItem == null) { cartItem = new EB_C_CartItem(); cartItem.setItem(item); cartItem.setQuantity(0); itemMap.put(item.getItemid(), cartItem); } cartItem.incrementQuantity(); } public EB_C_Item removeItemById(String itemId) {/** 刪除EB_C_Item* */ EB_C_CartItem cartItem = itemMap.remove(itemId); if (cartItem == null) {return null; } else { return cartItem.getItem(); } } public void incrementQuantityByItemId(String itemId) {/** 增 加 EB_C_Item的數量 */ EB_C_CartItem cartItem = itemMap.get(itemId); cartItem.incrementQuantity(); } public void setQuantityByItemId(String itemId, int quantity) {/** 設 置EB_C_Item的數量* */ EB_C_CartItem cartItem = itemMap.get(itemId); cartItem.setQuantity(quantity); } public BigDecimal getSubTotal() { /** 計算價格* */ BigDecimal subTotal = new BigDecimal("0"); Iterator<EB_C_CartItem> items = getCartItems(); while (items.hasNext()) { EB_C_CartItem cartItem = (EB_C_CartItem) items.next(); EB_C_Item item = cartItem.getItem(); BigDecimal listPrice = new BigDecimal(item.getListprice()); BigDecimal quantity = new BigDecimal(String.valueOf(cartItem. getQuantity())); subTotal = subTotal.add(listPrice.multiply(quantity)); } return subTotal; } }
在購物車應用中,對應域對象操作的數據訪問JavaBean對象包括有EB_C_ProductDAO對象、EB_C_CategoryDAO對象以及EB_C_ItemDAO對象等。
其中EB_C_ProductDAO實現對產品信息訪問,其中定義兩個接口方法:getProductByID(String productid),用于根據產品ID查找對應產品詳細信息;getAllProduct(),用于查找所有產品。EB_C_ProductDAO.java源代碼詳見【代碼1-19】。
【代碼1-19】 EB_C_ProductDAO.java文件。
public class EB_C_ProductDAO { //略去數據庫操作屬性定義 public EB_C_Product getProductByID(String productid){ //根據ID查找產品信息 EB_C_Product product=null; conn = new EBusDb().getCon(); //獲取數據庫連接對象 //構建SQL語句:根據產品ID查找產品信息 String sqlbyid="select * from eb_c_product where productid=?"; try { pstmt=conn.prepareStatement(sqlbyid); ////建立預處理對象 pstmt.setString(1,productid); //給占位符賦值 rs=pstmt.executeQuery(); //執行查詢 if(rs.next()){//迭代結果,是否存在符合條件記錄 product=new EB_C_Product(); product.setProductid(rs.getString("productid")); product.setName(rs.getString("name")); product.setDescn(rs.getString("descn")); product.setCateid(rs.getString("cateid")); } } catch (SQLException e) { e.printStackTrace(); } finally{ ebusdb.closedb(rs, stmt, pstmt, conn); } return product; } public Collection<EB_C_Product> getAllProduct(){//查找所有的產品 Collection<EB_C_Product> coll=new ArrayList<EB_C_Product>(); conn = new EBusDb().getCon(); String sqlall="select * from eb_c_product"; try { stmt=conn.createStatement();////建立預處理對象 rs=stmt.executeQuery(sqlall); //執行查詢 while(rs.next()){//迭代結果 EB_C_Product product=new EB_C_Product(); product.setCateid(rs.getString("cateid")); product.setName(rs.getString("name")); product.setDescn(rs.getString("descn")); product.setProductid(rs.getString("productid")); coll.add(product); } } catch (SQLException e) { e.printStackTrace(); } finally{ ebusdb.closedb(rs, stmt, pstmt, conn); } return coll; } }
EB_C_CategoryDAO實現對產品種類信息訪問,其中定義兩個接口方法:getCategoryByID (String cateid),用于根據產品種類ID查找對應產品種類詳細信息;getAllCategory(),用于查找所有產品種類。EB_C_CategoryDAO.java源代碼詳見【代碼1-20】。
【代碼1-20】 EB_C_CategoryDAO.java文件。
public class EB_C_CategoryDAO { //略去數據庫操作屬性定義 public EB_C_Category getCategoryByID(String cateid){ //根據ID查找產品 種類信息 EB_C_Category category=null; conn = new EBusDb().getCon(); String sqlbyid="select * from eb_c_category where cateid=?"; try { pstmt=conn.prepareStatement(sqlbyid); ////建立預處理對象 pstmt.setString(1,cateid); //給占位符賦值 rs=pstmt.executeQuery(); //執行查詢 if(rs.next()){//迭代結果,是否存在符合條件記錄 category=new EB_C_Category(); category.setCateid(rs.getString("cateid")); category.setName(rs.getString("name")); category.setDescn(rs.getString("descn")); } } catch (SQLException e) { e.printStackTrace(); }finally{ ebusdb.closedb(rs, stmt, pstmt, conn); } return category; } public Collection<EB_C_Category> getAllCategory(){//查找所有的產品種類 Collection<EB_C_Category> coll=new ArrayList<EB_C_Category>(); conn = new EBusDb().getCon(); String sqlall="select * from eb_c_category"; try { stmt=conn.createStatement(); ////建立預處理對象 rs=stmt.executeQuery(sqlall); //執行查詢 while(rs.next()){//迭代結果 EB_C_Category category=new EB_C_Category(); category.setCateid(rs.getString("cateid")); category.setName(rs.getString("name")); category.setDescn(rs.getString("descn")); coll.add(category); } } catch (SQLException e) { e.printStackTrace(); }finally{ ebusdb.closedb(rs, stmt, pstmt, conn); } return coll; } }
EB_C_ItemDAO實現對商品信息訪問,其中定義兩個接口方法:getItemByID(String itemid),用于根據商品ID查找對應商品詳細信息;getItemByProductID(String productid),用于根據產品ID查找該產品對應的所有商品。EB_C_ItemDAO.java源代碼詳見【代碼1-21】。
【代碼1-21】 EB_C_ItemDAO.java文件。
public class EB_C_ItemDAO { //略去數據庫操作屬性定義 public EB_C_Item getItemByID(String itemid){ //根據ID查找商品信息 EB_C_Item item=null; conn = new EBusDb().getCon(); String sqlbyid="select * from eb_c_item where itemid=?"; try { pstmt=conn.prepareStatement(sqlbyid); ////建立預處理對象 pstmt.setString(1,itemid); //給占位符賦值 rs=pstmt.executeQuery(); //執行查詢 if(rs.next()){//迭代結果,是否存在符合條件記錄 item=new EB_C_Item(); item.setItemid(rs.getString("itemid")); //略去部分代碼,從數據庫表字段獲取值封裝在item對象中 } } catch (SQLException e) { e.printStackTrace(); }finally{ ebusdb.closedb(rs, stmt, pstmt, conn); } } return item; //根據產品ID查找所有商品信息 public Collection<EB_C_Item> getItemByProductID(String productid){ Collection<EB_C_Item> coll=new ArrayList<EB_C_Item>(); onn = new EBusDb().getCon(); String sqlallbyproductid="select * from eb_c_item where productid=?"; try { pstmt=conn.prepareStatement(sqlallbyproductid); ////建立預處理 對象 pstmt.setString(1,productid); //給占位符賦值 rs=pstmt.executeQuery(); //執行查詢 while(rs.next()){//迭代結果 EB_C_Item item=new EB_C_Item(); item.setItemid(rs.getString("itemid")); //略去部分代碼,從數據庫表字段獲取值封裝在item對象中 coll.add(item);//將item對象添加到集合容器中 } } catch (SQLException e) { e.printStackTrace(); }finally{ ebusdb.closedb(rs, stmt, pstmt, conn); } return coll; } }
5.創建視圖組件
在struts應用中,通常會把FormBean對象作為視圖組件,在本節購物車應用中,需要構建FormBean對象EB_C_CartForm,用來表示購物車,該對象包含了購物車域對象EB_C_Cart,而EB_C_Cart域對象又包含了EB_C_CartItem域對象。EB_C_CartForm、EB_C_Cart、EB_C_CartItem三者之間的關系如圖1-43所示。

圖1-43 EB_C_CartForm、EB_C_Cart、EB_C_CartItem關系圖
EB_C_CartForm和EB_C_Cart是一種組合關系,EB_C_CartForm對象直接由EB_C_Cart對象組合而成;同樣,EB_C_Cart對象與EB_C_CartItem對象也是一種組合關系,EB_C_Cart對象由多個EB_C_CartItem對象組合而成。
在整個在線購物的B2C電子商務網站實現中,由于有很多地方會構建FormBean對象,而這些對象中都需要進行表單校驗,因此將基礎的表單校驗方法單獨定義在一個基本的FormBean中,這樣其他的FromBean可以繼承它從而減少代碼的重復。定義基本的FormBean為EB_BasicForm對象,其詳情如【代碼1-22】所示。
【代碼1-22】 EB_BasicForm.java文件。
public class EB_BasicForm extends ActionForm { public ActionErrors validate(ActionMapping mapping,HttpServletRequest request) { ActionErrors actionErrors = null; ArrayList<String> errorList = new ArrayList<String>(); doValidate(mapping, request, errorList); request.setAttribute("errors", errorList); if (!errorList.isEmpty()) { actionErrors = new ActionErrors(); actionErrors.add(ActionErrors.GLOBAL_ERROR, new ActionError ("global.error")); } return actionErrors; } public void doValidate(ActionMapping mapping,HttpServletRequest request, List<String> errors) {} protected void addErrorIfStringEmpty(List<String>errors,String message, String value) { if (value == null || value.trim().length() < 1)errors.add(message); } }
EB_C_CartForm繼承了EB_BasicForm,它有一個屬性,就是EB_C_Cart。其詳情如【代碼1-23】所示。
【代碼1-23】 EB_C_CartForm.java文件。
public class EB_C_CartForm extends EB_BasicForm { private EB_C_Cart cart = new EB_C_Cart(); private String theItemId; // 當前正在操作的ItemId //屬性對應的getter、setter方法 public void reset(ActionMapping mapping, HttpServletRequest request) { super.reset(mapping, request); theItemId = null; } }
將FormBean配置在Struts核心文件struts-config.xml中,配置代碼如【代碼1-24】所示。
【代碼1-24】 struts-config.xml中的FormBean配置片段。
<!-- 表單 Bean --> <form-beans> <form-bean name="basicForm" type="com.etop.topebus.view.forms.EB_ BasicForm"></form-bean> <form-bean name="cartForm" type="com.etop.topebus.view.forms.EB_C_ CartForm"> </form-bean> </form-beans>
購物車應用是基于Struts實現的,為了更好地表現Struts的應用,我們在頁面文件中采用Struts標簽,用以替代原來在JSP頁面中出現的Java Script。為此,需要在使用Struts標簽之前將Struts系列標簽庫引入到頁面文件中。
我們首先需要將Struts標簽庫的描述文件放到WEB-INF目錄下,這里包括struts-logic.tld、struts-html.tld、struts-bena.tld、struts-tiles.tld、struts-nested.tld共5個文件。然后修改web.xml配置文件,在其中加入這些tld文件的定位代碼:
<!-- Struts Tag Library Descriptors --> <taglib> <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib>
為了通用性,我們將Struts標簽庫在公共的頁頭文件中導入,因此,需要修改header.jsp內容,在其中添加如下代碼:
<%@ taglib uri="../WEB-INF/struts-logic.tld" prefix="logic" %> <%@ taglib uri="../WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="../WEB-INF/struts-bean.tld" prefix="bean" %>
視圖組件除了必要的FormBean組件以外,還包括一系列的JSP頁面文件,這里我們構建購物車應用頁面文件包括有eb_c_cart.jsp和eb_c_checkout.jsp。
eb_c_cart.jsp主要用來顯示購物車的狀態,并且提供了更新購物車狀態的操作。頁面中采用Struts的Logic標簽庫包含的邏輯運算標簽如equal、notEqual運算來對EB_C_CartForm中的cart.numberOfItems進行判斷,如果結果和0相當,那么就在瀏覽器中顯示標記包含中的代碼,否則,不顯示這段代碼。
在eb_c_cart.jsp中采用Struts的Logic標簽庫中包含的迭代器標簽iterate,用來將購物車中所有的商品項信息顯示出來:
<logic:iterate id="cartItem" name="cartForm" property="cart.cartItems">
它相當于:
<% Iterator<EB_C_CartItem> cartItems=cartForm.getCart().getCartItems(); EB_C_CartItem cartItem; while(cartItems.hasNext()){cartItem=cartsItems.next(); %> <td><%=cartItem.getItem().getProduct().getName() %></td> <td><%=cartItem.getItem().getAttr1() %></td> <%}%>
eb_c_cart.jsp頁面文件詳情如【代碼1-25】所示。
【代碼1-25】 eb_c_cart.jsp文件。
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> <!-- 包含頭部JSP --> <%@ include file="/include/header.jsp"%><br> <table border="0" width="1050" cellspacing="0" cellpadding="0" align= "center"> <tr><td valign="top" align="center"><h2 align="center">購物車</h2> <html:form action="/cart/updateItem.do" method="post"> <TABLE class=font1 cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width="99%" align=center bgColor=#ffffff borderColorLight=#003686 border=1> <tr bgcolor="#C4E669"> <td><b>項目 ID</b></td><td><b>產品 ID</b></td> <td><b>說明</b></td><td><b>數量</b></td> <td><b>價格</b></td><td> </td> </tr> <!-- 如果cart.numberOfItems是0,表示還沒有往購物車中添加商品 --> <logic:equal name="cartForm" property="cart.numberOfItems" value="0"> <tr bgcolor="#fffdd7"> <td colspan="6"><b>購物車中沒有貨物.</b></td> </tr> </logic:equal> <!-- 利用struts迭代器標簽顯示商品信息 --> <logic:iterate id="cartItem" name="cartForm" property= "cart.cartItems"> <tr bgcolor="#fffdd7"><td><b> <html:link paramId="itemId" paramName="cartItem" paramProperty="item.itemid" page="/product/viewItem. jsp"> <bean:write name="cartItem" property="item. itemid" /> </html:link></b> </td> <td><bean:write name="cartItem" property="item. productid" /></td> <td> <!-- 輸出商品的信息 --> <bean:write name="cartItem" property="item. product.name" /> <bean:write name="cartItem" property="item. attr1" /> <bean:write name="cartItem" property="item. attr2" /> <bean:write name="cartItem" property="item. attr3" /> <bean:write name="cartItem" property="item. attr5" /> </td> <td align="center"> <!-- 更新商品數量的輸入框 --> <input type="text" size="3" name="<bean:write name="cartItem" property="item.itemid"/>" value="<bean:write name="cartItem" property="quantity"/>" /> </td> <td align="right"> <bean:write name="cartItem" property="item. listprice" /> </td> <td> <html:link paramId="theItemId" paramName= "cartItem" paramProperty="item.itemid" page="/cart/ removeItem.do"> <img border="0" src="../images/button_ remove.gif" /> </html:link> </td> </tr> </logic:iterate> <tr bgcolor="#fffdd7"> <td colspan="5" align="right"> <b>小計: <bean:write name="cartForm" property="cart. subTotal" /></b> <br /><input type="image" border="0" src="../images/ button_update _cart.gif" name="update" /> </td> <td> </td> </tr> </table> </html:form> <!-- 如果cart.numberOfItems是0,那么不顯示結賬鏈接 --> <logic:notEqual name="cartForm" property="cart.numberOfItems" value="0"> <br /> <center> <html:link page="/cart/eb_c_checkout.jsp"> <img border="0" src="../images/button_checkout.gif" /> </html:link> </center> </logic:notEqual> </td> </tr> </table><br> <!-- 包含尾部JSP --> <%@ include file="/include/footer.jsp"%>
eb_c_checkout.jsp表示對購物車中的購物信息進行統計展示,并提供返回購物車和進行結賬操作的入口,其頁面如【代碼1-26】所示。
【代碼1-26】 eb_c_checkout.jsp文件。
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> <!-- 包含頭部JSP --> <%@ include file="/include/header.jsp"%><br> <table border="0" width="1050" cellspacing="0" cellpadding="0" align= "center"> <tr> <td valign="top" align="center"> <h2 align="center"> <html:link page="/cart/eb_c_cart.jsp"><< 購物車</html: link> ::購物統計 </h2> <TABLE class=font1 cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width="99%" align=center bgColor=#ffffff borderColorLight=#003686 border=1> <tr bgcolor="#C4E669"> <td><b>項目 ID</b></td><td><b>產品 ID</b></td> <td><b> 介 紹 </b></td><td><b> 數 量 </b></td><td><b> 價 格 </b></td> </tr> <logic:iterate id="cartItem" name="cartForm" property="cart.cartItems"> <tr bgcolor="#fffdd7"> <td> <b><html:link paramId="itemid"paramName="cartItem" paramProperty="item.itemid" page="/product/ viewItem.jsp"> <bean:write name="cartItem" property= "item.itemid" /> </html:link></b> </td> <td> <bean:write name="cartItem" property="item. productid" /> </td> <td> <bean:write name="cartItem" property="item.product. name" /> <bean:write name="cartItem"property="item.attr1"/> <bean:write name="cartItem"property="item.attr2"/> <bean:write name="cartItem"property="item.attr3"/> <bean:write name="cartItem"property="item.attr5"/> </td> <td align="center"> <bean:write name="cartItem" property="quantity" /> </td> <td align="right"> <bean:write name="cartItem" property="item. listprice" /> </td> </tr> </logic:iterate> <tr bgcolor="#fffdd7"> <td colspan="5" align="right"> <b>小計: <bean:write name="cartForm" property="cart. subTotal" /></b><br /> </td> </tr> </table><br /> <center> <!—購物車統計后,可以進行結賬處理,此處為結賬入口 --> <html:link page="/order/createOrderForm.do"> <img border="0" src="../images/button_continue.gif" /> </html:link> </center> </td> <td valign="top" width="20%" align="right"> </td> </tr> </table><br> <!-- 包含尾部JSP --> <%@ include file="/include/footer.jsp"%>
6.創建控制器組件
購物車應用中,包括向購物車中添加商品,更新購物車中某項商品的數量以及從購物車中刪除某項商品,因此我們在實現過程中定義多個控制器組件來實現上述功能,包括AddItemAction組件用以處理添加商品項、RemoveItemAction組件用于處理刪除商品項以及UpdateItemAction組件用以更新商品項的數量。
AddItemAction核心方法execute,它操作處理客戶請求的過程,如果EB_C_Cart中已經存在有商品項EB_C_Item,那么就增加這個EB_C_Item的數量;否則,在EB_C_Cart中添加這個商品項EB_C_Item。AddItemAction.java文件源代碼如【代碼1-27】所示。
【代碼1-27】 AddItemAction.java文件。
public class AddItemAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { EB_C_CartForm cartForm = (EB_C_CartForm) form; EB_C_Cart cart = cartForm.getCart(); String theItemId = cartForm.getTheItemId(); <!—如果購物車中已經存在該商品項,則直接添加該商品項的數量;否則,添加這個商品項 --> if (cart.containsItemId(theItemId)) { cart.incrementQuantityByItemId(theItemId); } else { EB_C_ItemDAO dao = new EB_C_ItemDAO(); EB_C_Item item = dao.getItemByID(theItemId); cartForm.getCart().addItem(item); } <!—添加商品項處理成功,頁面轉發到“success”所代表的邏輯視圖 --> return mapping.findForward("success"); } }
由于向購物車中添加商品項或增加商品項的數量成功后,頁面會被轉發到success所代表的邏輯視圖,而邏輯視圖則在struts-config.xml文件中配置,其對應有物理視圖頁面cart/eb_c_cart.jsp。該控制器組件在struts-config.xml文件中配置片段為:
<action name="cartForm" path="/cart/addItem" scope="session" type="com.etop.topebus.control.action.AddItemAction"> <forward name="success" path="/cart/eb_c_cart.jsp"></forward> </action>
其中,name屬性對應FormBean組件EB_C_CartForm配置邏輯名;path屬性對應頁面請求路徑,即頁面form表單中action屬性所對應值;type屬性對應控制器組件的完整限定名稱類;scope屬性表示所配置的控制器作用范圍。
UpdateItemAction組件更新購物車中商品數量,UpdateItemAction.java文件源代碼如【代碼1-28】所示。
【代碼1-28】 UpdateItemAction.java文件。
public class UpdateItemAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { EB_C_CartForm cartForm = (EB_C_CartForm) form; Iterator<EB_C_CartItem>cartItems=cartForm.getCart().getCartItems(); while (cartItems.hasNext()) { EB_C_CartItem cartItem = cartItems.next(); String itemId = cartItem.getItem().getItemid(); try { int quantity = Integer.parseInt(request.getParameter(itemid)); cartForm.getCart().setQuantityByItemId(itemId, quantity); if (quantity < 1) cartItems.remove(); } catch (Exception e) {} } return mapping.findForward("success"); } }
相應的,該控制器組件在struts-config.xml文件中配置片段為:
<action name="cartForm" path="/cart/updateItem" scope="session" type="com.etop.topebus.control.action.UpdateItemAction"> <forward name="success" path="/cart/eb_c_cart.jsp"></forward> </action>
RemoveItemAction組件用于刪除購物車中商品,RemoveItemAction.java文件源代碼如【代碼1-29】所示。
【代碼1-29】 RemoveItemAction.java文件。
public class RemoveItemAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { EB_C_CartForm cartForm = (EB_C_CartForm) form; EB_C_Item item = cartForm.getCart().removeItemById(cartForm. getTheItemId()); if (item == null) { request.setAttribute("message","Attempted to remove null CartItem from Cart."); return mapping.findForward("error"); } else { return mapping.findForward("success"); } } }
相應的,該控制器組件在struts-config.xml文件中配置片段為:
<action name="cartForm" path="/cart/removeItem" scope="session" type="com.etop.topebus.control.action.RemoveItemAction"> <forward name="success" path="/cart/eb_c_cart.jsp"></forward> </action>
在RemoveItemAction組件中,當從購物車中刪除商品發生問題的時候,請求將被轉發到一個叫error的邏輯視圖中,該邏輯視圖同樣在struts-config.xml文件中配置,其物理視圖對應整個應用的全局異常頁面。配置信息如下:
<!-- 全局轉發 --> <global-forwards> <forward name="error" path="/include/error.jsp"></forward> </global-forwards>
7.部署運行購物車應用
至此,已經將在線購物的B2C電子商務網站中的購物車應用完全實現。結合注冊登錄應用,重新部署一下項目TopEBus即可完成請求。
- 程序設計與實踐(VB.NET)
- 云原生Spring實戰
- Learn Programming in Python with Cody Jackson
- Hands-On Swift 5 Microservices Development
- 可解釋機器學習:模型、方法與實踐
- Scala Reactive Programming
- ASP.NET程序開發范例寶典
- Unity 3D/2D移動開發實戰教程
- OpenCV Android Programming By Example
- WordPress Search Engine Optimization(Second Edition)
- 青少年Python趣味編程
- Swift Essentials(Second Edition)
- Lync Server Cookbook
- 三步學Python
- Java Web程序員面試筆試寶典