官术网_书友最值得收藏!

  • 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>&nbsp;</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>&nbsp;</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">&lt;&lt; 購物車</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">    &nbsp;</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即可完成請求。

主站蜘蛛池模板: 柳州市| 沁阳市| 威信县| 永清县| 甘肃省| 台前县| 军事| 株洲县| 疏勒县| 襄城县| 南漳县| 永年县| 广水市| 北辰区| 梧州市| 定日县| 怀仁县| 镇安县| 延长县| 普洱| 景宁| 嘉定区| 厦门市| 昌黎县| 类乌齐县| 清涧县| 姚安县| 岚皋县| 琼结县| 宁阳县| 滨海县| 台湾省| 南康市| 永福县| 南郑县| 望都县| 永安市| 定边县| 西丰县| 梁平县| 海城市|