基于JSP+Servlet的多商家零食销售平台 - 源码深度解析

JavaJavaScriptHTMLCSSMySQLJSP+Servlet
2026-02-103 浏览

文章摘要

本系统是一个基于JSP和Servlet技术构建的B2B2C多商家零食在线销售平台。其核心业务价值在于为众多零食供应商提供了一个统一、自主的商品展示与交易空间,同时为终端消费者打造了一个品类丰富、选择多样的综合性购物集市。该平台有效解决了传统零食销售渠道单一、商家与消费者信息不对称、小型商家难以独立运...

随着互联网技术的快速发展,电子商务模式已经从传统的B2C向更加多元化的B2B2C模式演进。零食行业作为快消品的重要组成部分,面临着渠道分散、信息不对称、小型商家线上运营能力不足等挑战。多商家零食集市平台应运而生,它通过集中化的技术架构,为零食供应商提供统一的线上销售渠道,同时为消费者打造一站式购物体验。

本平台采用经典的J2EE MVC架构,前端使用JSP结合JSTL标签库进行页面渲染,业务逻辑层由Servlet控制器统一处理,数据持久层基于JDBC和DAO模式实现。这种分层架构确保了系统的高内聚低耦合,便于后续功能扩展和维护。

系统架构与技术栈

平台采用典型的三层架构设计,每一层都有明确的职责分工:

表示层:使用JSP技术结合JSTL标签库和EL表达式,实现动态页面渲染。通过严格的MVC分离,确保业务逻辑不侵入视图层。

// 典型的Servlet控制器示例
@WebServlet("/product/*")
public class ProductServlet extends HttpServlet {
    private ProductDAO productDAO;
    
    @Override
    public void init() throws ServletException {
        productDAO = new ProductDAOImpl();
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        String action = request.getPathInfo();
        switch (action) {
            case "/list":
                listProducts(request, response);
                break;
            case "/detail":
                showProductDetail(request, response);
                break;
            default:
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }
    
    private void listProducts(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        String categoryId = request.getParameter("categoryId");
        List<Product> products = productDAO.findByCategory(categoryId);
        request.setAttribute("products", products);
        request.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(request, response);
    }
}

业务逻辑层:Servlet作为控制器,负责请求路由、参数验证、业务处理和数据传递。每个功能模块都有对应的Servlet处理相关请求。

数据访问层:采用DAO设计模式,通过接口与实现类分离的方式,提供统一的数据访问接口。

// 商品数据访问接口
public interface ProductDAO {
    Product findById(int id);
    List<Product> findByCategory(String categoryId);
    List<Product> findByShop(String shopId);
    void save(Product product);
    void update(Product product);
    void delete(int id);
}

// JDBC实现类
public class ProductDAOImpl implements ProductDAO {
    private Connection getConnection() throws SQLException {
        return DataSourceManager.getConnection();
    }
    
    @Override
    public Product findById(int id) {
        String sql = "SELECT * FROM pros WHERE id = ?";
        try (Connection conn = getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setInt(1, id);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                return mapResultSetToProduct(rs);
            }
        } catch (SQLException e) {
            throw new RuntimeException("数据库查询失败", e);
        }
        return null;
    }
    
    private Product mapResultSetToProduct(ResultSet rs) throws SQLException {
        Product product = new Product();
        product.setId(rs.getInt("id"));
        product.setProshop(rs.getString("proshop"));
        product.setProname(rs.getString("proname"));
        product.setPrice(rs.getString("price"));
        product.setDiscount(rs.getString("discount"));
        product.setFilename(rs.getString("filename"));
        product.setBei(rs.getString("bei"));
        product.setExtbei(rs.getString("extbei"));
        product.setStatus(rs.getString("status"));
        product.setSavetime(rs.getString("savetime"));
        product.setCjnum(rs.getString("cjnum"));
        return product;
    }
}

数据库设计亮点分析

商品表(pros)设计优化

商品表作为核心业务表,其设计直接影响到系统性能和扩展性:

CREATE TABLE `pros` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `proshop` varchar(255) DEFAULT NULL COMMENT '商品店铺',
  `proname` varchar(255) DEFAULT NULL COMMENT '商品名称',
  `price` varchar(255) DEFAULT NULL COMMENT '商品价格',
  `discount` varchar(255) DEFAULT NULL COMMENT '折扣',
  `filename` varchar(255) DEFAULT NULL COMMENT '文件名',
  `bei` varchar(255) DEFAULT NULL COMMENT '备注',
  `extbei` varchar(255) DEFAULT NULL COMMENT '扩展备注',
  `status` varchar(255) DEFAULT NULL COMMENT '状态',
  `savetime` varchar(255) DEFAULT NULL COMMENT '保存时间',
  `cjnum` varchar(255) DEFAULT NULL COMMENT '成交数量',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='商品表'

设计亮点分析

  1. 字段类型优化:价格字段采用varchar类型存储,虽然在实际应用中建议使用DECIMAL类型确保精度,但varchar设计便于处理复杂的价格格式(如区间价格、促销价等)
  2. 扩展性设计:通过beiextbei两个备注字段,为商品信息提供了良好的扩展性,可以存储各种自定义属性
  3. 状态管理status字段支持商品上下架、审核等状态流转,cjnum字段记录成交数量便于热门商品推荐

商品类别表(splb)层级设计

类别表采用经典的父子层级结构,支持无限级分类:

CREATE TABLE `splb` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pid` varchar(255) DEFAULT NULL COMMENT '父级ID',
  `lbname` varchar(255) DEFAULT NULL COMMENT '类别名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='商品类别表'

层级查询优化方案

-- 递归查询所有子类别(MySQL 8.0+)
WITH RECURSIVE category_tree AS (
    SELECT id, pid, lbname, 1 as level
    FROM splb 
    WHERE pid = '0'
    UNION ALL
    SELECT c.id, c.pid, c.lbname, ct.level + 1
    FROM splb c
    INNER JOIN category_tree ct ON c.pid = ct.id
)
SELECT * FROM category_tree ORDER BY level, id;

-- 传统方法:应用层递归处理
public List<Category> buildCategoryTree(List<Category> allCategories) {
    Map<String, Category> categoryMap = new HashMap<>();
    List<Category> rootCategories = new ArrayList<>();
    
    // 建立ID到对象的映射
    for (Category category : allCategories) {
        categoryMap.put(String.valueOf(category.getId()), category);
    }
    
    // 构建树形结构
    for (Category category : allCategories) {
        if ("0".equals(category.getPid())) {
            rootCategories.add(category);
        } else {
            Category parent = categoryMap.get(category.getPid());
            if (parent != null) {
                parent.addChild(category);
            }
        }
    }
    return rootCategories;
}

订单表(prosorder)业务设计

订单表设计充分考虑了电商业务的复杂性:

CREATE TABLE `prosorder` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uname` varchar(255) DEFAULT NULL COMMENT '用户名',
  `savetime` varchar(255) DEFAULT NULL COMMENT '下单时间',
  `prosinfo` varchar(255) DEFAULT NULL COMMENT '商品信息',
  `toshop` varchar(255) DEFAULT NULL COMMENT '收货地址',
  `status` varchar(255) DEFAULT NULL COMMENT '订单状态',
  `fkstatus` varchar(255) DEFAULT NULL COMMENT '付款状态',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='商品订单表'

状态机设计实现

// 订单状态机管理
public class OrderStatusManager {
    private static final Map<String, List<String>> STATUS_FLOW = new HashMap<>();
    
    static {
        // 定义订单状态流转规则
        STATUS_FLOW.put("待付款", Arrays.asList("已付款", "已取消"));
        STATUS_FLOW.put("已付款", Arrays.asList("已发货", "退款中"));
        STATUS_FLOW.put("已发货", Arrays.asList("已完成", "退货中"));
        STATUS_FLOW.put("已完成", Collections.emptyList());
        STATUS_FLOW.put("已取消", Collections.emptyList());
    }
    
    public static boolean canChangeStatus(String currentStatus, String targetStatus) {
        return STATUS_FLOW.getOrDefault(currentStatus, Collections.emptyList())
                         .contains(targetStatus);
    }
}

核心功能实现详解

多商家商品展示系统

平台支持多个商家独立管理商品,前端通过统一的商品展示组件渲染不同商家的商品:

商品详情页面

商品查询服务实现

// 商品搜索和筛选服务
public class ProductSearchService {
    private ProductDAO productDAO;
    
    public ProductSearchService(ProductDAO productDAO) {
        this.productDAO = productDAO;
    }
    
    public SearchResult searchProducts(ProductSearchCriteria criteria) {
        StringBuilder sql = new StringBuilder("SELECT * FROM pros WHERE 1=1");
        List<Object> params = new ArrayList<>();
        
        if (StringUtils.isNotBlank(criteria.getKeyword())) {
            sql.append(" AND (proname LIKE ? OR bei LIKE ?)");
            params.add("%" + criteria.getKeyword() + "%");
            params.add("%" + criteria.getKeyword() + "%");
        }
        
        if (StringUtils.isNotBlank(criteria.getShopId())) {
            sql.append(" AND proshop = ?");
            params.add(criteria.getShopId());
        }
        
        if (StringUtils.isNotBlank(criteria.getCategoryId())) {
            sql.append(" AND id IN (SELECT product_id FROM product_category WHERE category_id = ?)");
            params.add(criteria.getCategoryId());
        }
        
        // 分页处理
        sql.append(" ORDER BY cjnum DESC LIMIT ? OFFSET ?");
        params.add(criteria.getPageSize());
        params.add((criteria.getPageNumber() - 1) * criteria.getPageSize());
        
        return executeSearch(sql.toString(), params.toArray());
    }
}

购物车与订单管理

购物车功能采用Session存储临时数据,确保用户体验的流畅性:

购物车页面

购物车业务逻辑

// 购物车管理服务
public class ShoppingCartService {
    private Map<String, CartItem> cartItems = new HashMap<>();
    
    public void addItem(Product product, int quantity) {
        String key = generateItemKey(product);
        CartItem existingItem = cartItems.get(key);
        
        if (existingItem != null) {
            existingItem.setQuantity(existingItem.getQuantity() + quantity);
        } else {
            CartItem newItem = new CartItem(product, quantity);
            cartItems.put(key, newItem);
        }
    }
    
    public void removeItem(String productId) {
        cartItems.remove(productId);
    }
    
    public BigDecimal calculateTotal() {
        return cartItems.values().stream()
                .map(item -> item.getProduct().getPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    
    public Order createOrder(String username, String shippingAddress) {
        Order order = new Order();
        order.setUname(username);
        order.setToshop(shippingAddress);
        order.setSavetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        order.setStatus("待付款");
        order.setFkstatus("未付款");
        
        String productsInfo = cartItems.values().stream()
                .map(item -> item.getProduct().getProname() + "×" + item.getQuantity())
                .collect(Collectors.joining(","));
        order.setProsinfo(productsInfo);
        
        return order;
    }
}

订单处理流程

订单处理采用状态模式管理订单生命周期:

订单管理页面

订单状态管理

// 订单状态处理上下文
public class OrderProcessor {
    private OrderState currentState;
    private Order order;
    
    public OrderProcessor(Order order) {
        this.order = order;
        this.currentState = OrderStateFactory.createState(order.getStatus());
    }
    
    public void pay() {
        currentState.pay(this);
    }
    
    public void ship() {
        currentState.ship(this);
    }
    
    public void complete() {
        currentState.complete(this);
    }
    
    public void cancel() {
        currentState.cancel(this);
    }
    
    public void setState(OrderState state) {
        this.currentState = state;
        // 更新数据库中的订单状态
        updateOrderStatus(state.getStatus());
    }
}

// 订单状态接口
public interface OrderState {
    void pay(OrderProcessor processor);
    void ship(OrderProcessor processor);
    void complete(OrderProcessor processor);
    void cancel(OrderProcessor processor);
    String getStatus();
}

// 待付款状态实现
public class PendingPaymentState implements OrderState {
    @Override
    public void pay(OrderProcessor processor) {
        // 处理支付逻辑
        processor.setState(new PaidState());
        // 记录支付日志
        logPayment(processor.getOrder());
    }
    
    @Override
    public void cancel(OrderProcessor processor) {
        processor.setState(new CancelledState());
        // 释放库存
        releaseInventory(processor.getOrder());
    }
}

新闻资讯系统

平台内置新闻发布系统,支持管理员发布平台公告和行业资讯:

新闻页面

新闻管理服务

// 新闻业务逻辑处理
public class NewsService {
    private NewsDAO newsDAO;
    
    public List<News> getLatestNews(int limit) {
        return newsDAO.findLatest(limit);
    }
    
    public void publishNews(News news) {
        news.setSavetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        newsDAO.save(news);
        
        // 可选:发送新消息通知
        notifySubscribers(news);
    }
    
    public Page<News> getNewsByType(String infoType, int page, int size) {
        return newsDAO.findByType(infoType, page, size);
    }
}

用户留言反馈系统

留言系统支持用户与平台互动,管理员可以及时回复用户反馈:

留言页面

留言处理Servlet

@WebServlet("/message/*")
public class MessageServlet extends HttpServlet {
    private MessageDAO messageDAO;
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        String action = request.getPathInfo();
        
        switch (action) {
            case "/add":
                addMessage(request, response);
                break;
            case "/reply":
                replyMessage(request, response);
                break;
            default:
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }
    
    private void addMessage(HttpServletRequest request, HttpServletResponse response) 
        throws IOException {
        String saver = request.getParameter("saver");
        String content = request.getParameter("content");
        
        Message message = new Message();
        message.setSaver(saver);
        message.setContent(content);
        message.setSavetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        
        messageDAO.save(message);
        
        response.sendRedirect(request.getContextPath() + "/message/success.jsp");
    }
}

实体模型设计

系统采用面向对象的设计思想,构建了完整的实体模型体系:

// 商品实体类
public class Product {
    private Integer id;
    private String proshop;
    private String proname;
    private String price;
    private String discount;
    private String filename;
    private String bei;
    private String extbei;
    private String status;
    private String savetime;
    private String cjnum;
    
    // 构造函数、getter、setter方法
    public Product() {}
    
    public BigDecimal getFinalPrice() {
        BigDecimal originalPrice = new BigDecimal(price);
        if (discount != null && !discount.isEmpty()) {
            BigDecimal discountRate = new BigDecimal(discount);
            return originalPrice.multiply(discountRate);
        }
        return originalPrice;
    }
    
    public boolean isAvailable() {
        return "上架".equals(status);
    }
}

// 订单实体类
public class Order {
    private Integer id;
    private String uname;
    private String savetime;
    private String prosinfo;
    private String toshop;
    private String status;
    private String fkstatus;
    
    public List<OrderItem> parseItems() {
        // 解析商品信息字符串为订单项列表
        return Arrays.stream(prosinfo.split(","))
                .map(item -> {
                    String[] parts = item.split("×");
                    return new OrderItem(parts[0], Integer.parseInt(parts[1]));
                })
                .collect(Collectors.toList());
    }
}

功能展望与优化方向

基于当前架构,平台有以下优化和发展方向:

1. 引入Redis缓存层

现状分析:商品信息、类别信息等热点数据频繁查询,直接访问数据库压力较大。

优化方案

// 缓存增强的商品服务
@Service
public class CachedProductService {
    private final ProductDAO productDAO;
    private final RedisTemplate<String, Object> redisTemplate;
    
    private static final String PRODUCT_KEY_PREFIX = "product:";
    private static final String CATEGORY_PRODUCTS_KEY_P
本文关键词
JSPServlet多商家平台零食销售源码解析

上下篇

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