在传统酒类销售领域,渠道单一、信息不对称、跨地域购买困难等问题长期制约着宁夏葡萄酒产业的发展。随着电子商务技术的成熟,构建一个专业化的在线销售平台成为打通产销链路、提升市场效率的关键路径。本系统采用经典的JSP+Servlet技术栈,打造了一个功能完备的B2C葡萄酒电商平台,为宁夏葡萄酒产区提供了数字化的销售解决方案。
系统采用分层架构设计,表现层使用JSP动态页面技术,通过JSTL标签库和EL表达式实现数据渲染,避免了在页面中嵌入Java代码,保证了视图层的纯净性。控制层由Servlet实现,负责请求分发、参数验证和业务逻辑调用。业务逻辑层封装了核心的电商功能,数据访问层采用DAO模式,通过JDBC与MySQL数据库进行交互。这种MVC架构确保了代码的可维护性和扩展性。

平台首页采用响应式设计,展示了葡萄酒商品分类、热门推荐和促销信息。顶部导航栏提供了完整的用户交互入口,包括商品搜索、购物车、用户登录等功能模块。轮播图区域支持管理员动态配置,可以灵活展示最新的营销活动。
数据库架构设计
系统使用MySQL数据库,共设计了20张数据表,涵盖了用户管理、商品管理、订单处理等核心业务模块。数据库设计遵循第三范式,确保了数据的一致性和完整性。
用户表设计
CREATE TABLE users (
user_id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
phone VARCHAR(20),
real_name VARCHAR(50),
gender ENUM('M','F','U') DEFAULT 'U',
birth_date DATE,
avatar_url VARCHAR(200),
membership_level INT DEFAULT 1,
registration_date DATETIME DEFAULT CURRENT_TIMESTAMP,
last_login_date DATETIME,
status ENUM('ACTIVE','INACTIVE','SUSPENDED') DEFAULT 'ACTIVE',
shipping_address TEXT
);
用户表采用纵向扩展设计,包含了完整的用户基本信息、会员等级管理和状态控制。password字段使用加密存储,确保用户信息安全。membership_level字段支持会员等级体系,为后续的会员权益差异化提供了基础。shipping_address字段采用TEXT类型,支持存储复杂的收货地址信息。
商品表设计
CREATE TABLE products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(200) NOT NULL,
brand_id INT NOT NULL,
category_id INT NOT NULL,
vintage YEAR,
alcohol_content DECIMAL(3,1),
volume_ml INT,
description TEXT,
price DECIMAL(10,2) NOT NULL,
original_price DECIMAL(10,2),
stock_quantity INT DEFAULT 0,
sales_volume INT DEFAULT 0,
image_url VARCHAR(200),
thumbnail_url VARCHAR(200),
seo_keywords VARCHAR(300),
seo_description VARCHAR(500),
is_featured BOOLEAN DEFAULT FALSE,
is_active BOOLEAN DEFAULT TRUE,
created_date DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_date DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (brand_id) REFERENCES brands(brand_id),
FOREIGN KEY (category_id) REFERENCES categories(category_id)
);
商品表设计充分考虑了葡萄酒产品的特殊性,包含年份(vintage)、酒精度(alcohol_content)、容量(volume_ml)等专业字段。价格体系支持原价和现价设置,便于促销活动管理。SEO相关字段为搜索引擎优化提供了支持,is_featured字段用于标识推荐商品。
订单表设计
CREATE TABLE orders (
order_id VARCHAR(32) PRIMARY KEY,
user_id INT NOT NULL,
order_status ENUM('PENDING','PAID','SHIPPED','DELIVERED','CANCELLED','REFUNDED') DEFAULT 'PENDING',
total_amount DECIMAL(10,2) NOT NULL,
shipping_fee DECIMAL(8,2) DEFAULT 0,
discount_amount DECIMAL(8,2) DEFAULT 0,
final_amount DECIMAL(10,2) NOT NULL,
shipping_address TEXT NOT NULL,
recipient_name VARCHAR(50) NOT NULL,
recipient_phone VARCHAR(20) NOT NULL,
payment_method ENUM('ALIPAY','WECHAT','BANK_TRANSFER') DEFAULT 'ALIPAY',
payment_status ENUM('UNPAID','PAID','REFUNDED') DEFAULT 'UNPAID',
payment_time DATETIME,
order_notes TEXT,
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
订单表采用业务主键设计,order_id使用32位字符串,便于分布式系统扩展。订单状态和支付状态分离管理,支持复杂的业务流程。金额字段细分设计,支持运费、折扣等复杂计算场景。
核心功能实现
用户认证与权限管理
系统采用基于Session的用户认证机制,支持用户和管理员双角色登录。认证流程通过Filter实现统一的访问控制。
public class AuthenticationFilter implements Filter {
private static final List<String> EXCLUDE_URLS = Arrays.asList(
"/login", "/register", "/static/", "/api/public/"
);
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String path = httpRequest.getRequestURI();
// 检查是否为排除路径
if (isExcludedPath(path)) {
chain.doFilter(request, response);
return;
}
HttpSession session = httpRequest.getSession(false);
if (session == null || session.getAttribute("currentUser") == null) {
httpResponse.sendRedirect(httpRequest.getContextPath() + "/login");
return;
}
// 权限验证
User user = (User) session.getAttribute("currentUser");
if (path.startsWith("/admin/") && !user.isAdmin()) {
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
chain.doFilter(request, response);
}
private boolean isExcludedPath(String path) {
return EXCLUDE_URLS.stream().anyMatch(path::startsWith);
}
}

登录界面采用简洁的设计风格,支持用户名/邮箱登录。后端采用BCrypt密码加密,确保用户凭证安全。
public class UserService {
private UserDAO userDAO = new UserDAO();
private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
public User authenticate(String username, String password) {
User user = userDAO.findByUsernameOrEmail(username);
if (user != null && passwordEncoder.matches(password, user.getPassword())) {
// 更新最后登录时间
userDAO.updateLastLogin(user.getUserId());
return user;
}
return null;
}
public boolean register(User user) {
if (userDAO.existsByUsername(user.getUsername())) {
throw new BusinessException("用户名已存在");
}
if (userDAO.existsByEmail(user.getEmail())) {
throw new BusinessException("邮箱已被注册");
}
// 加密密码
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userDAO.save(user) > 0;
}
}
商品展示与搜索功能
商品展示模块支持多维度分类浏览和全文搜索,采用分页技术优化大数据量下的性能表现。
public class ProductServlet extends HttpServlet {
private ProductService productService = new ProductService();
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getParameter("action");
switch (action) {
case "list":
showProductList(request, response);
break;
case "detail":
showProductDetail(request, response);
break;
case "search":
searchProducts(request, response);
break;
default:
showHomePage(request, response);
}
}
private void showProductList(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int categoryId = Integer.parseInt(request.getParameter("categoryId"));
int page = Integer.parseInt(request.getParameter("page"));
int pageSize = 12;
ProductQuery query = new ProductQuery();
query.setCategoryId(categoryId);
query.setPage(page);
query.setPageSize(pageSize);
PageResult<Product> result = productService.getProductsByCategory(query);
request.setAttribute("products", result.getData());
request.setAttribute("totalPages", result.getTotalPages());
request.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(request, response);
}
}

商品详情页展示了完整的商品信息,包括多角度图片、详细参数、用户评价等。采用AJAX技术实现购物车添加操作,提升用户体验。
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div class="product-detail">
<div class="product-images">
<img src="${product.imageUrl}" alt="${product.productName}">
</div>
<div class="product-info">
<h1>${product.productName}</h1>
<div class="price-section">
<span class="current-price">¥${product.price}</span>
<c:if test="${product.originalPrice > product.price}">
<span class="original-price">¥${product.originalPrice}</span>
</c:if>
</div>
<div class="product-specs">
<div class="spec-item">
<label>年份:</label>
<span>${product.vintage}</span>
</div>
<div class="spec-item">
<label>酒精度:</label>
<span>${product.alcoholContent}%vol</span>
</div>
</div>
<div class="add-to-cart">
<input type="number" id="quantity" value="1" min="1" max="${product.stockQuantity}">
<button onclick="addToCart(${product.productId})">加入购物车</button>
</div>
</div>
</div>
<script>
function addToCart(productId) {
const quantity = document.getElementById('quantity').value;
fetch('/cart/add', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId: productId, quantity: quantity})
}).then(response => response.json())
.then(data => {
if (data.success) {
updateCartCount(data.cartCount);
showMessage('添加成功');
} else {
showMessage('添加失败: ' + data.message);
}
});
}
</script>
购物车与订单管理
购物车模块采用Session存储临时数据,支持商品添加、数量修改、批量删除等操作。订单生成过程包含完整的库存验证和事务管理。
public class CartService {
public void addItem(HttpSession session, int productId, int quantity) {
Product product = productDAO.findById(productId);
if (product == null || !product.isActive()) {
throw new BusinessException("商品不存在或已下架");
}
if (product.getStockQuantity() < quantity) {
throw new BusinessException("库存不足");
}
Map<Integer, CartItem> cart = getCart(session);
CartItem item = cart.get(productId);
if (item != null) {
item.setQuantity(item.getQuantity() + quantity);
} else {
item = new CartItem(product, quantity);
cart.put(productId, item);
}
}
public Order createOrder(HttpSession session, OrderRequest orderRequest) {
Map<Integer, CartItem> cart = getCart(session);
if (cart.isEmpty()) {
throw new BusinessException("购物车为空");
}
Connection conn = null;
try {
conn = DatabaseUtil.getConnection();
conn.setAutoCommit(false);
// 验证库存并锁定
for (CartItem item : cart.values()) {
int affected = productDAO.lockStock(conn, item.getProduct().getProductId(),
item.getQuantity());
if (affected == 0) {
throw new BusinessException("商品库存不足: " + item.getProduct().getProductName());
}
}
// 创建订单
Order order = buildOrder(orderRequest, cart);
orderDAO.save(conn, order);
// 创建订单项
for (CartItem item : cart.values()) {
OrderItem orderItem = new OrderItem(order.getOrderId(), item);
orderItemDAO.save(conn, orderItem);
}
conn.commit();
clearCart(session);
return order;
} catch (SQLException e) {
if (conn != null) {
try { conn.rollback(); } catch (SQLException ex) {}
}
throw new RuntimeException("创建订单失败", e);
} finally {
DatabaseUtil.closeConnection(conn);
}
}
}

订单提交页面整合了收货地址选择、支付方式选择、优惠券使用等完整流程。采用事务确保数据一致性,防止超卖现象。
后台管理系统
后台管理模块采用RBAC权限模型,支持商品管理、订单处理、用户管理、内容管理等全方位功能。
public class AdminProductServlet extends HttpServlet {
private ProductService productService = new ProductService();
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getParameter("action");
try {
switch (action) {
case "add":
addProduct(request, response);
break;
case "update":
updateProduct(request, response);
break;
case "delete":
deleteProduct(request, response);
break;
case "batchUpdate":
batchUpdateProducts(request, response);
break;
}
} catch (BusinessException e) {
sendErrorResponse(response, e.getMessage());
}
}
private void addProduct(HttpServletRequest request, HttpServletResponse response)
throws IOException {
Product product = parseProductFromRequest(request);
productService.addProduct(product);
sendSuccessResponse(response, "添加成功");
}
}

后台商品管理界面支持批量操作、Excel导入导出、富文本编辑等高级功能。采用AJAX实现无刷新操作,提升管理效率。
实体模型与业务逻辑
系统采用面向对象的设计思想,构建了完整的实体模型体系。核心实体包括User、Product、Order、Category等,通过Service层封装复杂的业务逻辑。
订单状态机设计
订单生命周期管理采用状态模式,确保状态流转的合法性。
public class Order {
private String orderId;
private OrderStatus status;
private PaymentStatus paymentStatus;
public void pay() {
if (status != OrderStatus.PENDING) {
throw new IllegalStateException("只有待支付订单可以支付");
}
if (paymentStatus != PaymentStatus.UNPAID) {
throw new IllegalStateException("订单已支付");
}
this.paymentStatus = PaymentStatus.PAID;
this.status = OrderStatus.PAID;
this.paymentTime = new Date();
}
public void ship() {
if (status != OrderStatus.PAID) {
throw new IllegalStateException("只有已支付订单可以发货");
}
this.status = OrderStatus.SHIPPED;
this.shippingTime = new Date();
}
}
价格计算策略
支持多种促销策略的价格计算引擎,为营销活动提供技术支撑。
public interface PricingStrategy {
BigDecimal calculatePrice(Product product, int quantity);
}
public class DefaultPricingStrategy implements PricingStrategy {
public BigDecimal calculatePrice(Product product, int quantity) {
return product.getPrice().multiply(BigDecimal.valueOf(quantity));
}
}
public class DiscountPricingStrategy implements PricingStrategy {
private BigDecimal discountRate;
public DiscountPricingStrategy(BigDecimal discountRate) {
this.discountRate = discountRate;
}
public BigDecimal calculatePrice(Product product, int quantity) {
BigDecimal original = product.getPrice().multiply(BigDecimal.valueOf(quantity));
return original.multiply(discountRate);
}
}
性能优化与安全考虑
系统在性能和安全方面进行了多重优化。数据库连接池采用HikariCP,有效管理连接资源。SQL查询通过索引优化,提升查询效率。安全方面采用参数化查询防止SQL注入,XSS过滤防止跨站脚本攻击。
public class SecurityFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// XSS防护
XSSRequestWrapper wrappedRequest = new XSSRequestWrapper(httpRequest);
// CSRF防护
if ("POST".equalsIgnoreCase(httpRequest.getMethod())) {
String csrfToken = wrappedRequest.getParameter("csrfToken");
HttpSession session = httpRequest.getSession(false);
String sessionToken = session != null ?
(String) session.getAttribute("csrfToken") : null;
if (sessionToken == null || !sessionToken.equals(csrfToken)) {
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "无效的CSRF令牌");
return;
}
}
chain.doFilter(wrappedRequest, response);
}
}
技术架构演进展望
基于当前技术实现,系统在未来可以从以下几个方面进行架构升级和功能扩展:
- **微服务架构