購物車 是電商系統的核心功能之一。在不引入資料庫的輕量級場景下,利用 HttpSession 在伺服器端暫存使用者選購的商品,是快速原型開發與中小型專案的常見做法。本文提供完整的 Servlet 架構範例,涵蓋商品列表、加入購物車、查看購物車三大核心流程。
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ ListBook │────▶│ Buy │────▶│ SessionCount│
│ Servlet │ │ Servlet │ │ Demo │
│ (商品列表) │ │ (加入購物車) │ │ (查看購物車) │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ HttpSession │
│ List │
└─────────────┘
package cn.com.shopping;
public class Book {
private String id;
private String name;
private String author;
private String description;
public Book() {}
public Book(String id, String name, String author, String description) {
this.id = id;
this.name = name;
this.author = author;
this.description = description;
}
// Getter/Setter 略...
}
package cn.com.shopping;
import java.util.LinkedHashMap;
import java.util.Map;
class Db {
private static Map map = new LinkedHashMap<>();
static {
map.put("1", new Book("1", "Java Web 開發實戰", "王曉明", "經典入門好書"));
map.put("2", new Book("2", "Spring Boot 微服務", "張三", "進階實戰"));
map.put("3", new Book("3", "MySQL 效能調優", "李四", "DBA 必讀"));
map.put("4", new Book("4", "Redis 設計與實現", "趙五", "原理深度解析"));
map.put("5", new Book("5", "Kubernetes 實戰指南", "錢六", "容器編排權威"));
}
public static Map getAll() {
return map;
}
}
package cn.com.shopping;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class ListBookServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("本店商品列表:<br/>");
Map map = Db.getAll();
for (Map.Entry entry : map.entrySet()) {
Book book = entry.getValue();
// 使用 encodeURL 支援無 Cookie 環境下的 Session 追蹤
String url = response.encodeURL("/Session/BuyServlet?id=" + book.getId());
out.print(book.getName() + " <a href='" + url + "' target='_blank'>購買</a><br/>");
}
}
}
package cn.com.shopping;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class BuyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
Book book = Db.getAll().get(id);
// getSession(false) 不會強制建立新 Session,避免匿名使用者產生垃圾 Session
HttpSession session = request.getSession(false);
if (session == null) {
session = request.getSession(true); // 確認需要時才建立
}
@SuppressWarnings("unchecked")
List cart = (List) session.getAttribute("cart");
if (cart == null) {
cart = new ArrayList<>();
session.setAttribute("cart", cart);
}
cart.add(book);
// 重導向至購物車頁面,使用 encodeRedirectURL 維持 Session ID
String url = response.encodeRedirectURL("/Session/SessionCountDemo");
response.sendRedirect(url);
}
}
package cn.com.shopping;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class SessionCountDemo extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession(false);
if (session == null) {
out.write("您尚未購買任何商品!");
return;
}
@SuppressWarnings("unchecked")
List cart = (List) session.getAttribute("cart");
if (cart == null || cart.isEmpty()) {
out.write("購物車是空的!");
return;
}
out.write("您的購物車商品:<br/>");
for (Book book : cart) {
out.write("《" + book.getName() + "》 作者:" + book.getAuthor() + "<br/>");
}
out.write("<br/><a href='/Session/ListBookServlet'>繼續購物</a>");
}
}
| 技術點 | 說明 |
|---|---|
| Session 取得策略 | 先用 getSession(false) 檢查,避免匿名瀏覽產生大量無效 Session |
| URL 重寫 | 使用 encodeURL / encodeRedirectURL 支援禁用 Cookie 的瀏覽器 |
| 型別安全 | 搭配 @SuppressWarnings("unchecked") 與泛型 List |
| 資料結構選擇 | ArrayList 維持加入順序,適合購物車顯示需求 |
List 改為 Map 或建立 CartItem 類別包含數量、小計cart_items(user_id, book_id, quantity) 實現跨裝置同步HttpSessionListener 記錄棄單行為