本篇博客所完成的購物車應用重點主要落在頁面之間的轉換和數據的傳遞,對於前端界面設計並不多加分析。屬於初學 Web 編程階段。
該購物車應用主要有四個功能:查看商品列表、查看商品詳情、將商品加入購物車、顯示購物車信息、將商品從購物車中移除。
目錄
準備工作
該購物車應用有兩個主要對象,商品 和 購物車,所以需要構建 Product 類來存儲商品的信息,構建 ShoppingItem 來存儲購物車列表信息。
Product 類中包含商品的基本信息(如下),還有各個屬性的 set 和 get 方法。
private int id;//商品編號
private String name;//商品名稱
private String description;//商品描述
private float price;//商品價格
ShoppingItem 類存儲購物車信息,所以該類中包含相應商品及其購買數量,同樣不要忘記屬性的 set 和 get 方法。
private Product product;//商品信息
private int quantity;//商品數量
在我們功能的實現中,會將 Product 和 ShoppingItem 都存儲到 List 中(List<Product> products 和 List<ShoppingItem> cart),但是不同的的是,商品的信息是固定的,所以我們可以將存儲商品的信息的 List 放在Servlet 中,然而,客戶的購物車信息會在客戶的活動中發生變化,因此每個客戶需要有一個單獨的對象將其的購物車信息進行存儲,我們可以通過會話機制 HttpSession 實現。
當用戶登陸購物網站時,Web 服務器會爲客戶創建一個 HttpSession 對象,實現購物車的 Servlet 使用該會話對象存儲用戶的購物車對象 cart ,購物車中存儲着用戶購買的商品列表,當客戶向購物車中添加或刪除商品時, Servlet 就更新該列表,當客戶結賬時, Servlet 就會從會話中檢索購物車對象,從購物車中檢索商品列表並計算總價格。一旦客戶結算完成,容器就會關閉會話。如果客戶再發送另一個請求,就會創建一個新的會話。
在我們的功能實現之前,我們還要初始化我們的商品列表 products 。創建一個 ShoppingCartServlet 類,我們的所有功能都會在這裏實現,在 ShoppingCartServlet 的 init() 方法中初始化列表。
private List<Product> products = new ArrayList<Product>(); // products 存放所有商品的List對象
public void init() throws ServletException {
products.add(new Product(1, "單反相機", "尼康性價比最高的單反相機", 4159.95F));
products.add(new Product(2, "華爲手機", "華爲手機的最新手機P30", 3998.95F));
products.add(new Product(3, "筆記本電腦", "Mac新一代產品", 15000.51F));
products.add(new Product(4, "平板電腦", "蘋果公司新產品", 12000F));
}
設置映射即每個功能對應方法
ShoppingCartServlet 類時一個控制類,處理各種信息。我們剛剛已經在 init() 方法中初始化了商品列表,現在要在 web.xml 中設置映射和每個功能對應的方法了。
在 web.xml 中設置 ShoppingCartServlet 類 的映射
<servlet-mapping>
<servlet-name>ShoppingCartServlet</servlet-name>
<url-pattern>/ShoppingCartServlet</url-pattern>
<url-pattern>/products</url-pattern> 顯示商品列表
<url-pattern>/viewProductDetails</url-pattern> 顯示商品詳細內容
<url-pattern>/viewCart</url-pattern> 查看購物車
<url-pattern>/deleteItem</url-pattern> 從購物車中移除商品
<url-pattern>/addToCart</url-pattern> 向購物車中加入商品
</servlet-mapping>
在 doGet() 方法中設置每個功能對應的方法,因爲當我們按下 enter 鍵進行界面跳轉的時候就會觸發 doGet() 方法,在這個方法中就進行判斷顯然合情合理。
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
String uri = request.getRequestURI();// 得到當前界面的URI
if (uri.endsWith("/products"))
showProductList(response);
else if (uri.endsWith("/viewProductDetails"))
showProductDetails(request, response);
else if (uri.endsWith("/viewCart"))
showCart(request, response);
else if (uri.endsWith("/deleteItem"))
deleteItem(request, response);
else
showProductList(response);// 發送請求,調用get方法後首先顯示商品列表信息
}
由於在這裏觸及了幾個知識點,不禁想提出來,給大家思考回顧。
1. request 和 response 的區別。
2. URI 的結構、發展,以及URI 和 URL 、URN 的聯繫。(一篇比較詳細的博客: URI 詳解 )
查看商品列表
查看商品列表會看見以下頁面(括號中的時商品價格)
主要步驟:
1. 設置response 中的內容類型和所使用的字符集,得到 PrintWriter 對象。
2. 遍歷商品列表並將信息顯示出來,其中 ”詳細信息“ 採用超文本鏈接,並將商品的 id 號傳過去。(注意,id=product.getId() 中,等號和product.getId() 之間不可以出現空格,否則讀取 id 號時會出錯 ,即 NumberFormatException 錯誤)
// 超鏈接到商品詳情目錄
out.println("(<a href = 'viewProductDetails?id=" + product.getId()+ "'>詳細信息</a>)");
在顯示 商品詳細信息的方法中可以用以下語句得到傳過去的 id 號
productId = Integer.parseInt(request.getParameter("id"));
3. 設置 查看購物車 鏈接。
out.println("<a href = 'viewCart'>查看購物車</a>");//查看購物車鏈接
具體代碼如下:
private void showProductList(HttpServletResponse response)throws IOException {
response.setContentType("text/html;charset = UTF-8");//設置數據的內容類型和使用的字符集
PrintWriter out = response.getWriter();
out.println("<html><head><title>商品列表</title></head>");
out.println("<body><p>商品列表</p>");
out.println("<ul>");
for (Product product : products) {
// 顯示商品名稱和價格
out.println("<li>" + product.getName() + "(" + product.getPrice()+ ")");
// 超鏈接到商品詳情目錄
out.println("(<a href = 'viewProductDetails?id=" + product.getId()+ "'>詳細信息</a>)");
}
out.println("</ul>");
out.println("<a href = 'viewCart'>查看購物車</a>");//查看購物車鏈接
out.println("</body></html>");
}
查看商品詳情
查看商品詳情的頁面如下:
其中,讓我們看看這個頁面的URI
其中我們在查看商品列表的方法中設置了”詳細信息“ 鏈接的URI,即查看商品詳情的URI 的 path 最後爲 viewProductDetails ,並且把商品的 id 一併傳了過來,由於我們按的是 ”單反相機“ ,所以顯示的 id 號爲 1。
主要步驟:
1. 得到傳過來的 id 號。
int productId = 0; // 商品的Id號,用來檢索商品
//得到傳過來的 id 號
try {
productId = Integer.parseInt(request.getParameter("id"));
} catch (NumberFormatException e) {
e.printStackTrace();
}
2. 根據 id 號檢索 products 列表得到相應的商品。
private Product getProduct(int id) {
for (Product product : products) {
if (product.getId() == id)
return product;
}
return null;
}
3. 顯示商品的信息
4. 設置購買按鈕
out.println("<td><input name = 'quantity'/></td>"); //輸入商品數量
out.println("<td><input type = 'submit' value = '購買'/></td></tr>");
5. 設置商品列表鏈接
out.println("<tr><td colspan = '2'>"+ "<a href = 'products'>商品列表</a></td></tr>");
詳細代碼如下:
private void showProductDetails(HttpServletRequest request,HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset = UTF-8");
PrintWriter out = response.getWriter();
int productId = 0; // 商品的Id號,用來檢索商品
//得到傳過來的 id 號
try {
productId = Integer.parseInt(request.getParameter("id"));
} catch (NumberFormatException e) {
e.printStackTrace();
}
// 根據商品id返回商品對象
Product product = getProduct(productId);
if (product != null) {
out.println("<html><head><title>商品詳細信息</title></head>");
out.println("<body><p>商品詳細信息</p>");
out.println("<form method = 'post' action = 'addToCart'>");
// 這裏使用隱藏表單域存儲商品號信息
out.println("<input type = 'hidden' name = 'id' value = '"
+ productId + "'/>");
out.println("<table>");
out.println("<tr><td>商品名:</td><td>" + product.getName()
+ "</td></tr>");
out.println("<tr><td>說明:</td><td>" + product.getDescription()
+ "</td></tr>");
out.println("<tr><td>價格:</td><td>" + product.getPrice()
+ "</td></tr>");
out.println("<tr><tr>");
out.println("<td><input name = 'quantity'/></td>"); //輸入商品數量
out.println("<td><input type = 'submit' value = '購買'/></td></tr>");
out.println("<tr><td colspan = '2'>"+ "<a href = 'products'>商品列表</a></td></tr>");
out.println("</table>");
out.println("</form></body>");
} else {
out.println("No product found");
}
}
將商品加入購物車
當我們在商品的詳細信息頁面中輸入商品數量並點擊購買按鈕時,我們會觸發該 Servlet 的 doPost() 方法,因此,我們可以在doPost()方法中將商品加入購物車。
具體步驟如下:
1. 得到要加入購物車的商品的 id 和 數量
int productId = 0;
int quantity = 0;
// 得到要加入購物車中的商品ID和數量
try {
productId = Integer.parseInt(request.getParameter("id"));
quantity = Integer.parseInt(request.getParameter("quantity"));
} catch (NumberFormatException e) {
e.printStackTrace();
}
2. 得到 id 對應的商品
Product product = getProduct(productId);
3. 得到會話對象,並在會話對象中查找購物車對象 cart
// 在會話對象中查找購物車對象
HttpSession session = request.getSession();
List<ShoppingItem> cart = (ArrayList<ShoppingItem>) session.getAttribute("cart");
4. 檢查該 cart 對象是否爲 null ,若爲null 則創建一個 cart 列表對象(ArrayList<ShoppingItem>)
if (cart == null) {
// 若購物車爲空,則創建購物車並將其加入到session中
cart = new ArrayList<ShoppingItem>();
session.setAttribute("cart", cart);
}
若不爲 null ,則檢查購物車之前是否添加過同一種商品, 若有,將item中的quantity更新,並移除上一條信息
else {
for (int i = 0; i < cart.size(); i++) {
ShoppingItem subItem = cart.get(i); //得到購物車列表消息
int subProductId = subItem.getProduct().getId();
if(subProductId == productId){ //若購物車中以加入過該商品
quantity += subItem.getQuantity(); //更新商品數量
cart.remove(subItem);//移除上一條信息
break;
}
}
}
5. 建立購物車條目,並將其加入到 cart 對象中
ShoppingItem item = new ShoppingItem(product, quantity);
cart.add(item);
同樣,這裏也有很有意思的問題,在這裏我們使用了 HttpSession ,雖然沒有使用 Cookie ,但是,我認爲大家可以同樣思考清楚
HttpSession 和 Cookie 的具體功能分別是什麼,有什麼不同,兩者有哪些優缺點。
6. 最後可以考慮跳回商品列表頁面
具體代碼如下:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int productId = 0;
int quantity = 0;
// 得到要加入購物車中的商品ID和數量
try {
productId = Integer.parseInt(request.getParameter("id"));
quantity = Integer.parseInt(request.getParameter("quantity"));
} catch (NumberFormatException e) {
e.printStackTrace();
}
// 得到該ID對應的商品
Product product = getProduct(productId);
if (product != null && quantity >= 0) {
// 在會話對象中查找購物車對象
HttpSession session = request.getSession();
List<ShoppingItem> cart = (ArrayList<ShoppingItem>) session.getAttribute("cart");
if (cart == null) {
// 若購物車爲空,則創建購物車並將其加入到session中
cart = new ArrayList<ShoppingItem>();
session.setAttribute("cart", cart);
} else {
// 不爲空時,檢查購物車之前是否添加過同一種商品
// 若有,將item中的quantity更新,並移除上一條信息,退出循環
// 若無,則直接加入
for (int i = 0; i < cart.size(); i++) {
ShoppingItem subItem = cart.get(i); //得到購物車列表消息
int subProductId = subItem.getProduct().getId();
if(subProductId == productId){ //若購物車中以加入過該商品
quantity += subItem.getQuantity(); //更新商品數量
cart.remove(subItem);//移除上一條信息
break;
}
}
}
// 建立購物車條目,並將其加入到 cart 對象中
ShoppingItem item = new ShoppingItem(product, quantity);
cart.add(item);
}
// 添加成功後返回商品列表
showProductList(response);
}
顯示購物車信息
查看購物車頁面內容如下:
具體步驟如下:
1. 得到 httpSession 對象和 cart 購物車對象
2. 設置商品列表鏈接
out.println("<body><a href = 'products'>商品列表</a>");
3. 設置第一行信息並設置列寬
out.println("<table>");
out.println("<tr><td style='width:50px'>數量</td>");
out.println("<td style='width:80px'>商品</td>");
out.println("<td style='width:80px'>價格</td>");
out.println("<td style='width:80px'>小計</td>");
out.println("<td style='width:80px'>是否刪除</td></tr>");
4. 從購物車對象中得到商品信息並打印出來,還要計算其總價格 ( total )和 小計
在設置刪除鏈接時記的把要刪除商品的 id 號傳過去
out.println("<td><a href = 'deleteItem?id="+ product.getId() + "'>刪除</a></td>");
具體代碼如下:
private void showCart(HttpServletRequest request,HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset = UTF-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession(); // 得到會話對象
List<ShoppingItem> cart = (ArrayList<ShoppingItem>) session.getAttribute("cart");//得到 cart
//第一行的信息
out.println("<html?<head><title>購物車</title></head>");
out.println("<body><a href = 'products'>商品列表</a>");
out.println("<table>");
out.println("<tr><td style='width:50px'>數量</td>");
out.println("<td style='width:80px'>商品</td>");
out.println("<td style='width:80px'>價格</td>");
out.println("<td style='width:80px'>小計</td>");
out.println("<td style='width:80px'>是否刪除</td></tr>");
// 從購物車對象中得到商品信息並打印出來
if (cart != null) {
double total = 0.0;
for (int i = 0; i < cart.size(); i++) {
ShoppingItem item = cart.get(i);
Product product = item.getProduct();
int quantity = item.getQuantity();
if (quantity != 0) {
out.println("<tr><td>" + quantity + "</td>");
out.println("<td>" + product.getName() + "</td>");
out.println("<td>" + product.getPrice() + "</td>");
double subtotal = product.getPrice() * quantity;// 得到該商品的價格小計
out.println("<td>" + subtotal + "</td>");
out.println("<td><a href = 'deleteItem?id="+ product.getId() + "'>刪除</a></td>");
out.println("</tr>");
total += subtotal;
}
}
out.println("<tr><td colspan='4' style='text-align:right'>總計:"+ total + "</td></tr>");
out.println("</table>");
}
out.println("</table></body></html>");
}
將商品從購物車中移除
這個功能的實現較爲簡單
1. 得到 會話對象,再得到 cart 購物車列表對象
2. 得到傳過來的商品 id
3. 遍歷購物車中的商品,找到與刪除商品id號相同的購物車商品信息,並將之移除出購物車
具體代碼如下:
private void deleteItem(HttpServletRequest request,HttpServletResponse response) throws IOException {
// 得到會話對象
HttpSession session = request.getSession();
// 得到購物車對象
List<ShoppingItem> cart = (ArrayList<ShoppingItem>)session.getAttribute("cart");
// 得到刪除商品的id號
int productId = Integer.parseInt(request.getParameter("id"));
// 遍歷購物車中的商品,找到與刪除商品id號相同的購物車商品信息,並將之移除出購物車
for (int i = 0; i < cart.size(); i++) {
ShoppingItem item = cart.get(i);
Product product = item.getProduct();
int subProductId = product.getId();
if (subProductId == productId) {
cart.remove(item);
break;
}
}
showCart(request, response);
}
- 到這裏,這個購物車應用的基本功能就實現了,當然,這個應用還非常的粗糙,但是千里之行始於足下,一步步學習終會越來越好。如果各位發現什麼問題或者有什麼可以一起交流歡迎留言。