基于JSP+Servlet的在线奶茶销售平台 - 源码深度解析

JavaJavaScriptHTMLCSSMySQLJSP+Servlet
2026-02-195 浏览

文章摘要

本项目是一个基于JSP和Servlet技术构建的在线奶茶销售平台,旨在为奶茶店提供一个功能完备、稳定可靠的线上销售与管理解决方案。其核心业务价值在于将传统线下点单流程数字化,有效解决了实体店铺因高峰期顾客排队等待、人工记录订单易出错、以及营业数据统计困难等核心痛点。通过在线浏览菜单、一键下单和后台集...

在传统奶茶行业数字化转型的浪潮中,一个高效、稳定的线上销售平台成为提升竞争力的关键。本系统采用经典的JSP+Servlet技术栈,构建了一个功能完善的在线奶茶订购与管理系统,实现了从商品展示、购物车管理、订单处理到后台管理的全流程数字化。

系统采用浏览器/服务器架构,严格遵循MVC设计模式。Servlet作为控制器层负责处理所有业务逻辑和请求转发,JSP作为视图层实现数据展示,JavaBean作为模型层封装业务数据,MySQL数据库提供持久化存储。这种分层架构确保了代码的可维护性和系统的可扩展性。

数据库架构设计与技术亮点

数据库设计是整个系统的核心基础,采用了8张核心表来支撑业务逻辑。其中几个关键表的设计体现了良好的规范化思想和性能考量。

商品表(easybuy_product)的设计体现了电商系统的核心要素:

CREATE TABLE `easybuy_product` (
  `EP_ID` int(10) NOT NULL AUTO_INCREMENT COMMENT '商品ID',
  `EP_NAME` varchar(255) NOT NULL COMMENT '商品名称',
  `EP_DESCRIPTION` varchar(512) DEFAULT NULL COMMENT '商品描述',
  `EP_PRICE` decimal(10,2) NOT NULL COMMENT '商品价格',
  `EP_STOCK` decimal(10,0) NOT NULL COMMENT '商品库存',
  `EPC_ID` decimal(10,0) DEFAULT NULL COMMENT '分类ID',
  `EPC_CHILD_ID` decimal(10,0) DEFAULT NULL COMMENT '子分类ID',
  `EP_FILE_NAME` varchar(255) DEFAULT NULL COMMENT '商品图片文件名',
  PRIMARY KEY (`EP_ID`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT

该表设计的亮点在于:使用decimal(10,2)类型精确存储价格,避免浮点数精度问题;通过EPC_IDEPC_CHILD_ID实现商品的多级分类;EP_FILE_NAME字段存储图片路径而非直接存储图片,优化数据库性能;采用BTREE索引提升查询效率。

订单详情表(easybuy_order_detail) 采用与主订单表分离的设计:

CREATE TABLE `easybuy_order_detail` (
  `EOD_ID` int(10) NOT NULL AUTO_INCREMENT COMMENT '订单详情ID',
  `EO_ID` decimal(10,0) NOT NULL COMMENT '订单ID',
  `EP_ID` decimal(10,0) NOT NULL COMMENT '商品ID',
  `EOD_QUANTITY` decimal(6,0) NOT NULL COMMENT '商品数量',
  `EOD_COST` decimal(10,2) NOT NULL COMMENT '商品金额',
  PRIMARY KEY (`EOD_ID`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8

这种设计支持一个订单包含多个商品,符合实际业务场景。EOD_COST字段存储下单时的商品快照价格,确保历史订单数据的准确性,即使商品后续调价也不受影响。

购物车表(easybuy_shop) 的设计考虑了用户并发操作:

CREATE TABLE `easybuy_shop` (
  `es_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '购物车ID',
  `es_ep_file_name` varchar(255) DEFAULT NULL COMMENT '商品图片文件名',
  `es_ep_name` varchar(64) DEFAULT NULL COMMENT '商品名称',
  `es_ep_price` decimal(10,0) DEFAULT NULL COMMENT '商品价格',
  `es_eod_quantity` int(11) DEFAULT NULL COMMENT '商品数量',
  `es_ep_stock` int(11) DEFAULT NULL COMMENT '商品库存',
  `es_ep_id` int(11) DEFAULT NULL COMMENT '商品ID',
  `es_eu_user_id` varchar(64) DEFAULT NULL COMMENT '用户ID',
  `es_valid` int(11) DEFAULT NULL COMMENT '是否有效',
  PRIMARY KEY (`es_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8

该表通过es_valid字段实现软删除,保留用户购物车历史记录;冗余存储商品名称、价格等信息,减少联表查询,提升性能。

实体模型与数据封装

系统采用标准的JavaBean作为实体类,实现数据与业务的分离。以评论实体为例:

package com.hr.entity;

public class EASYBUY_COMMENT {
    private int EC_ID;
    private String EC_CONTENT;
    private String EC_CREATE_TIME;
    private String EC_REPLY;
    private String EC_REPLY_TIME;
    private String EC_NICK_NAME;
    
    public EASYBUY_COMMENT(int eCID, String eCCONTENT, String eCCREATETIME,
            String eCREPLY, String eCREPLYTIME, String eCNICKNAME) {
        EC_ID = eCID;
        EC_CONTENT = eCCONTENT;
        EC_CREATE_TIME = eCCREATETIME;
        EC_REPLY = eCREPLY;
        EC_REPLY_TIME = eCREPLYTIME;
        EC_NICK_NAME = eCNICKNAME;
    }
    
    public EASYBUY_COMMENT() {
    }
    
    // Getter和Setter方法
    public int getEC_ID() {
        return EC_ID;
    }
    public void setEC_ID(int eCID) {
        EC_ID = eCID;
    }
    // 其他getter/setter方法...
}

这种设计符合JavaBean规范,支持反射操作,便于Servlet和JSP之间的数据传递。实体类通过重载构造方法支持不同的初始化场景。

核心功能实现深度解析

1. 用户登录与身份验证

用户登录功能通过Servlet实现安全的身份验证机制。系统采用Session管理用户状态,确保不同角色用户的权限隔离。

用户登录界面

登录Servlet的核心处理逻辑包含密码验证、Session创建和权限判断:

// 伪代码示例:登录验证逻辑
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        
        UserDAO userDAO = new UserDAO();
        User user = userDAO.findByUsername(username);
        
        if (user != null && user.getPassword().equals(encrypt(password))) {
            HttpSession session = request.getSession();
            session.setAttribute("currentUser", user);
            session.setMaxInactiveInterval(30 * 60); // 30分钟超时
            
            // 根据用户角色跳转到不同页面
            if ("admin".equals(user.getRole())) {
                response.sendRedirect("admin/index.jsp");
            } else {
                response.sendRedirect("index.jsp");
            }
        } else {
            request.setAttribute("errorMsg", "用户名或密码错误");
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
    }
}

2. 商品分类浏览与搜索

系统实现多级商品分类展示,用户可按类别浏览商品,支持关键词搜索。

按分类浏览商品

商品查询Servlet处理分类查询和搜索请求:

public class ProductServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String categoryId = request.getParameter("categoryId");
        String keyword = request.getParameter("keyword");
        String pageStr = request.getParameter("page");
        int page = (pageStr == null) ? 1 : Integer.parseInt(pageStr);
        int pageSize = 12;
        
        ProductDAO productDAO = new ProductDAO();
        List<Product> productList;
        int totalCount;
        
        if (categoryId != null && !categoryId.isEmpty()) {
            // 按分类查询
            productList = productDAO.findByCategory(categoryId, page, pageSize);
            totalCount = productDAO.countByCategory(categoryId);
        } else if (keyword != null && !keyword.isEmpty()) {
            // 按关键词搜索
            productList = productDAO.search(keyword, page, pageSize);
            totalCount = productDAO.countBySearch(keyword);
        } else {
            // 查询所有商品
            productList = productDAO.findAll(page, pageSize);
            totalCount = productDAO.countAll();
        }
        
        int totalPages = (int) Math.ceil((double) totalCount / pageSize);
        
        request.setAttribute("productList", productList);
        request.setAttribute("currentPage", page);
        request.setAttribute("totalPages", totalPages);
        request.getRequestDispatcher("product-list.jsp").forward(request, response);
    }
}

对应的JSP页面使用JSTL和EL表达式展示商品列表:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div class="product-grid">
    <c:forEach var="product" items="${productList}">
        <div class="product-item">
            <img src="images/${product.epFileName}" alt="${product.epName}">
            <h3>${product.epName}</h3>
            <p class="price">¥${product.epPrice}</p>
            <p class="description">${product.epDescription}</p>
            <a href="productDetail?id=${product.epId}" class="btn-detail">查看详情</a>
            <button class="btn-cart" onclick="addToCart(${product.epId})">加入购物车</button>
        </div>
    </c:forEach>
</div>

<!-- 分页控件 -->
<div class="pagination">
    <c:if test="${currentPage > 1}">
        <a href="?page=${currentPage - 1}">上一页</a>
    </c:if>
    
    <c:forEach begin="1" end="${totalPages}" var="i">
        <c:choose>
            <c:when test="${i == currentPage}">
                <span class="current">${i}</span>
            </c:when>
            <c:otherwise>
                <a href="?page=${i}">${i}</a>
            </c:otherwise>
        </c:choose>
    </c:forEach>
    
    <c:if test="${currentPage < totalPages}">
        <a href="?page=${currentPage + 1}">下一页</a>
    </c:if>
</div>

3. 购物车管理与订单生成

购物车功能实现商品添加、数量修改、删除等操作,支持实时价格计算。

加入购物车功能

购物车Servlet处理商品添加逻辑:

public class CartServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String action = request.getParameter("action");
        String productId = request.getParameter("productId");
        String quantityStr = request.getParameter("quantity");
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("currentUser");
        
        if (user == null) {
            response.getWriter().write("请先登录");
            return;
        }
        
        CartDAO cartDAO = new CartDAO();
        
        if ("add".equals(action)) {
            int quantity = Integer.parseInt(quantityStr);
            CartItem existingItem = cartDAO.findByUserAndProduct(user.getUserId(), 
                Integer.parseInt(productId));
            
            if (existingItem != null) {
                // 更新数量
                cartDAO.updateQuantity(existingItem.getEsId(), 
                    existingItem.getEsEodQuantity() + quantity);
            } else {
                // 新增商品
                cartDAO.addItem(user.getUserId(), Integer.parseInt(productId), quantity);
            }
            response.getWriter().write("success");
            
        } else if ("update".equals(action)) {
            int quantity = Integer.parseInt(quantityStr);
            cartDAO.updateQuantity(Integer.parseInt(request.getParameter("cartId")), quantity);
            response.getWriter().write("success");
            
        } else if ("delete".equals(action)) {
            cartDAO.deleteItem(Integer.parseInt(request.getParameter("cartId")));
            response.getWriter().write("success");
        }
    }
}

订单生成过程中涉及库存检查和事务处理:

public class OrderService {
    public boolean createOrder(Order order, List<OrderDetail> details) {
        Connection conn = null;
        try {
            conn = DatabaseUtil.getConnection();
            conn.setAutoCommit(false);
            
            // 检查库存
            for (OrderDetail detail : details) {
                Product product = productDAO.findById(detail.getEpId(), conn);
                if (product.getEpStock() < detail.getEodQuantity()) {
                    throw new RuntimeException("商品库存不足: " + product.getEpName());
                }
            }
            
            // 生成订单
            int orderId = orderDAO.insert(order, conn);
            
            // 生成订单详情并更新库存
            for (OrderDetail detail : details) {
                detail.setEoId(orderId);
                orderDetailDAO.insert(detail, conn);
                
                // 更新商品库存
                productDAO.updateStock(detail.getEpId(), 
                    -detail.getEodQuantity(), conn);
            }
            
            // 清空购物车
            cartDAO.clearByUser(order.getEuUserId(), conn);
            
            conn.commit();
            return true;
            
        } catch (Exception e) {
            if (conn != null) {
                try { conn.rollback(); } catch (SQLException ex) {}
            }
            return false;
        } finally {
            DatabaseUtil.closeConnection(conn);
        }
    }
}

4. 后台管理系统

后台管理提供商品管理、订单处理、用户管理等功能,实现业务全流程监控。

订单管理系统

订单管理Servlet实现多状态订单查询和处理:

public class AdminOrderServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String status = request.getParameter("status");
        String pageStr = request.getParameter("page");
        int page = (pageStr == null) ? 1 : Integer.parseInt(pageStr);
        
        OrderDAO orderDAO = new OrderDAO();
        List<Order> orders;
        int totalCount;
        
        if (status != null && !status.isEmpty()) {
            orders = orderDAO.findByStatus(status, page, 10);
            totalCount = orderDAO.countByStatus(status);
        } else {
            orders = orderDAO.findAll(page, 10);
            totalCount = orderDAO.countAll();
        }
        
        request.setAttribute("orders", orders);
        request.setAttribute("currentPage", page);
        request.setAttribute("totalPages", (int) Math.ceil((double) totalCount / 10));
        request.getRequestDispatcher("/admin/order-list.jsp").forward(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String action = request.getParameter("action");
        String orderId = request.getParameter("orderId");
        
        if ("updateStatus".equals(action)) {
            String newStatus = request.getParameter("newStatus");
            OrderDAO orderDAO = new OrderDAO();
            boolean success = orderDAO.updateStatus(Integer.parseInt(orderId), newStatus);
            
            response.setContentType("application/json");
            PrintWriter out = response.getWriter();
            out.write("{\"success\": " + success + "}");
        }
    }
}

系统优化与功能扩展方向

基于当前系统架构,未来可从以下几个方向进行深度优化和功能扩展:

1. 性能优化与缓存机制 引入Redis缓存层,缓存热点商品数据、用户会话信息:

// Redis缓存示例
public class ProductService {
    private static final String PRODUCT_CACHE_KEY = "product:";
    private static final int CACHE_EXPIRE = 3600; // 1小时
    
    public Product findById(int productId) {
        String cacheKey = PRODUCT_CACHE_KEY + productId;
        String cached = redisClient.get(cacheKey);
        
        if (cached != null) {
            return JSON.parseObject(cached, Product.class);
        } else {
            Product product = productDAO.findById(productId);
            if (product != null) {
                redisClient.setex(cacheKey, CACHE_EXPIRE, JSON.toJSONString(product));
            }
            return product;
        }
    }
}

2. 支付系统集成 集成微信支付、支付宝等第三方支付平台:

public class PaymentService {
    public PaymentResult wechatPay(Order order, String openid) {
        WechatPayRequest request = new WechatPayRequest();
        request.setAppid(wechatConfig.getAppid());
        request.setMchId(wechatConfig.getMchId());
        request.setBody("奶茶订单-" + order.getOrderNumber());
        request.setOutTradeNo(order.getOrderNumber());
        request.setTotalFee(order.getTotalAmount().multiply(new BigDecimal(100)).intValue());
        request.setOpenid(openid);
        
        return wechatPayClient.unifiedOrder(request);
    }
}

3. 智能推荐系统 基于用户行为数据实现个性化推荐:

public class RecommendationService {
    public List<Product> recommendProducts(String userId, int limit) {
        // 基于协同过滤算法
        List<UserBehavior> behaviors = behaviorDAO.findByUser(userId);
        Map<String, Double> userVector = buildUserVector(behaviors);
        
        return productDAO.findSimilarProducts(userVector, limit);
    }
    
    private Map<String, Double> buildUserVector(List<UserBehavior> behaviors) {
        // 构建用户兴趣向量
        return behaviors.stream()
            .collect(Collectors.groupingBy(
                UserBehavior::getProductId,
                Collectors.summingDouble(UserBehavior::getWeight)
            ));
    }
}

4. 移动端适配与PWA支持 开发响应式界面,支持PWA技术实现原生应用体验:

<!-- PWA Manifest -->
<link rel="manifest" href="/manifest.json">
<!-- Service Worker注册 -->
<script>
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js')
        .then(registration => console.log('SW registered'))
        .catch(error => console
本文关键词
JSPServlet在线奶茶销售平台源码解析数据库设计

上下篇

上一篇
没有更多文章
下一篇
没有更多文章