基于JSP+Servlet的游戏商城管理系统 - 源码深度解析

JavaScriptHTMLCSSMySQLJSP+Servlet
2026-02-121 浏览

文章摘要

本项目是一款基于JSP与Servlet技术构建的游戏商城后台管理系统,旨在为中小型游戏发行商或独立开发者提供一个功能完整、易于维护的数字化商品交易管理平台。其核心业务价值在于解决了传统手工或半自动化方式管理游戏上架、订单、用户及库存时效率低下、易出错的核心痛点。系统通过集中化的Web管理界面,实现了...

游戏商城管理平台是采用经典J2EE Model 1架构构建的数字化商品交易管理解决方案。该系统针对中小型游戏发行商和独立开发者的实际业务需求,通过集中化的Web管理界面实现了游戏商品、用户账户、销售订单和财务数据的统一管控,有效解决了传统手工管理方式效率低下、易出错的核心痛点。

系统架构与技术栈

平台采用分层架构设计,严格遵循J2EE规范。前端视图层使用JSP技术负责动态页面渲染,内嵌JSTL标签库简化逻辑判断与数据循环操作。后端控制层由Servlet担当,作为系统的核心调度器,负责接收HTTP请求、进行参数校验与业务逻辑分发。数据模型层通过封装了核心业务逻辑的JavaBean组件实现,与MySQL数据库进行交互。

技术栈配置如下:

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.25</version>
    </dependency>
</dependencies>

数据库连接采用JDBC标准接口,通过连接池技术优化资源利用。整个系统将显示、控制和数据处理清晰分离,为团队协作和后续功能扩展提供了良好的基础。

数据库设计亮点分析

商品表设计优化

商品表(goods)的设计体现了高度的业务实用性和性能考量。表结构采用多图片字段设计,支持商品封面和详情图片的分别存储:

CREATE TABLE `goods` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品ID',
  `name` varchar(45) DEFAULT NULL COMMENT '商品名称',
  `cover` varchar(45) DEFAULT NULL COMMENT '商品封面',
  `image1` varchar(45) DEFAULT NULL COMMENT '商品图片1',
  `image2` varchar(45) DEFAULT NULL COMMENT '商品图片2',
  `price` float DEFAULT 0 COMMENT '商品价格',
  `intro` varchar(300) DEFAULT NULL COMMENT '商品介绍',
  `stock` int(11) DEFAULT NULL COMMENT '商品库存',
  `type_id` int(11) DEFAULT NULL COMMENT '商品类型ID',
  PRIMARY KEY (`id`),
  KEY `fk_type_id_idx` (`type_id`),
  CONSTRAINT `fk_type_id` FOREIGN KEY (`type_id`) REFERENCES `type` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=188 DEFAULT CHARSET=utf8 COMMENT='商品表'

设计亮点包括:

  • 字段长度优化:商品名称采用varchar(45)长度,平衡存储效率与业务需求
  • 价格字段默认值:price字段设置默认值0,防止空值导致的业务异常
  • 外键索引优化:为type_id字段建立索引,提升分类查询性能
  • 文本字段长度规划:intro字段采用varchar(300)满足商品描述需求

订单项表的关系设计

订单项表(orderitem)作为连接订单和商品的核心桥梁,其设计体现了复杂业务关系的优雅处理:

CREATE TABLE `orderitem` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单项ID',
  `price` float DEFAULT NULL COMMENT '商品单价',
  `amount` int(11) DEFAULT NULL COMMENT '商品数量',
  `goods_id` int(11) DEFAULT NULL COMMENT '商品ID',
  `order_id` int(11) DEFAULT NULL COMMENT '订单ID',
  PRIMARY KEY (`id`),
  KEY `fk_order_id_idx` (`order_id`),
  KEY `fk_orderitem_goods_id_idx` (`goods_id`),
  CONSTRAINT `fk_order_id` FOREIGN KEY (`order_id`) REFERENCES `order` (`id`),
  CONSTRAINT `fk_orderitem_goods_id` FOREIGN KEY (`goods_id`) REFERENCES `goods` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8 COMMENT='订单项表'

关键设计特点:

  • 价格历史记录:独立存储下单时的商品价格,确保订单数据的完整性
  • 双重外键约束:同时关联订单和商品表,维护数据一致性
  • 复合索引策略:为两个外键字段分别建立索引,优化关联查询性能

推荐系统的灵活架构

推荐表(recommend)采用类型字段实现多场景推荐功能,展现了灵活的业务扩展能力:

CREATE TABLE `recommend` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '推荐ID',
  `type` tinyint(1) DEFAULT NULL COMMENT '推荐类型',
  `goods_id` int(11) DEFAULT NULL COMMENT '商品ID',
  PRIMARY KEY (`id`),
  KEY `fk_goods_id_idx` (`goods_id`),
  CONSTRAINT `fk_goods_id` FOREIGN KEY (`goods_id`) REFERENCES `goods` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8 COMMENT='推荐表'

创新设计包括:

  • 级联删除:设置ON DELETE CASCADE,自动清理无效推荐记录
  • 类型字段扩展性:tinyint类型支持多种推荐场景(热门、新品、特价等)
  • 最小化数据冗余:通过外键关联避免重复存储商品信息

数据库结构

核心功能实现详解

用户身份验证与权限管理

系统采用双角色权限体系,通过isadmin字段区分管理员和普通用户。登录验证Servlet实现核心认证逻辑:

@WebServlet("/login")
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");
        
        UserService userService = new UserService();
        User user = userService.login(username, password);
        
        if (user != null) {
            if (user.getIsvalidate()) {
                HttpSession session = request.getSession();
                session.setAttribute("user", user);
                
                if (user.getIsadmin()) {
                    response.sendRedirect("admin/index.jsp");
                } else {
                    response.sendRedirect("index.jsp");
                }
            } else {
                request.setAttribute("msg", "账户未验证,请检查邮箱验证邮件");
                request.getRequestDispatcher("login.jsp").forward(request, response);
            }
        } else {
            request.setAttribute("msg", "用户名或密码错误");
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
    }
}

权限拦截器确保安全访问:

public class AuthFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, 
            FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        HttpSession session = req.getSession(false);
        
        String path = req.getRequestURI();
        if (path.contains("/admin/")) {
            if (session == null || session.getAttribute("user") == null) {
                res.sendRedirect(req.getContextPath() + "/login.jsp");
                return;
            }
            
            User user = (User) session.getAttribute("user");
            if (!user.getIsadmin()) {
                res.sendRedirect(req.getContextPath() + "/error/403.jsp");
                return;
            }
        }
        
        chain.doFilter(request, response);
    }
}

管理员登录

商品管理功能实现

商品管理模块支持完整的CRUD操作,包含图片上传和库存管理功能:

@WebServlet("/admin/goods")
public class GoodsServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        String action = request.getParameter("action");
        GoodsService goodsService = new GoodsService();
        
        switch (action) {
            case "add":
                addGoods(request, response, goodsService);
                break;
            case "edit":
                editGoods(request, response, goodsService);
                break;
            case "delete":
                deleteGoods(request, response, goodsService);
                break;
        }
    }
    
    private void addGoods(HttpServletRequest request, HttpServletResponse response, 
            GoodsService goodsService) throws ServletException, IOException {
        
        // 文件上传处理
        String uploadPath = getServletContext().getRealPath("/uploads");
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) uploadDir.mkdir();
        
        Goods goods = new Goods();
        goods.setName(request.getParameter("name"));
        goods.setPrice(Float.parseFloat(request.getParameter("price")));
        goods.setStock(Integer.parseInt(request.getParameter("stock")));
        goods.setIntro(request.getParameter("intro"));
        goods.setTypeId(Integer.parseInt(request.getParameter("type_id")));
        
        // 处理多图片上传
        Part coverPart = request.getPart("cover");
        if (coverPart != null && coverPart.getSize() > 0) {
            String coverFileName = generateFileName(coverPart);
            coverPart.write(uploadPath + File.separator + coverFileName);
            goods.setCover(coverFileName);
        }
        
        boolean success = goodsService.addGoods(goods);
        if (success) {
            response.sendRedirect("goods_manage.jsp?msg=添加成功");
        } else {
            request.setAttribute("error", "添加失败");
            request.getRequestDispatcher("goods_add.jsp").forward(request, response);
        }
    }
}

商品列表分页查询实现:

public class GoodsService {
    public PageBean<Goods> getGoodsByPage(int pageNo, int pageSize, String keyword, Integer typeId) {
        PageBean<Goods> pageBean = new PageBean<>();
        pageBean.setPageNo(pageNo);
        pageBean.setPageSize(pageSize);
        
        // 计算总记录数
        int totalCount = goodsDao.getGoodsCount(keyword, typeId);
        pageBean.setTotalCount(totalCount);
        
        // 计算总页数
        int totalPage = (totalCount + pageSize - 1) / pageSize;
        pageBean.setTotalPage(totalPage);
        
        // 获取当前页数据
        int start = (pageNo - 1) * pageSize;
        List<Goods> goodsList = goodsDao.getGoodsList(start, pageSize, keyword, typeId);
        pageBean.setList(goodsList);
        
        return pageBean;
    }
}

商品管理界面

购物车与订单处理

购物车功能采用Session存储,确保用户交互的流畅性:

public class CartServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        String action = request.getParameter("action");
        HttpSession session = request.getSession();
        Map<Integer, CartItem> cart = getCart(session);
        
        switch (action) {
            case "add":
                addToCart(request, cart);
                break;
            case "update":
                updateCart(request, cart);
                break;
            case "remove":
                removeFromCart(request, cart);
                break;
        }
        
        session.setAttribute("cart", cart);
        response.sendRedirect("cart.jsp");
    }
    
    private void addToCart(HttpServletRequest request, Map<Integer, CartItem> cart) {
        int goodsId = Integer.parseInt(request.getParameter("goods_id"));
        int amount = Integer.parseInt(request.getParameter("amount"));
        
        GoodsService goodsService = new GoodsService();
        Goods goods = goodsService.getGoodsById(goodsId);
        
        if (cart.containsKey(goodsId)) {
            CartItem item = cart.get(goodsId);
            item.setAmount(item.getAmount() + amount);
        } else {
            CartItem item = new CartItem(goods, amount);
            cart.put(goodsId, item);
        }
    }
}

订单创建流程包含事务管理和库存验证:

public class OrderService {
    public boolean createOrder(Order order, List<CartItem> cartItems) {
        Connection conn = null;
        try {
            conn = DataBaseUtil.getConnection();
            conn.setAutoCommit(false);
            
            // 验证库存
            for (CartItem item : cartItems) {
                if (!checkStock(conn, item.getGoods().getId(), item.getAmount())) {
                    conn.rollback();
                    return false;
                }
            }
            
            // 插入订单主表
            OrderDao orderDao = new OrderDao(conn);
            int orderId = orderDao.addOrder(order);
            
            // 插入订单明细并更新库存
            OrderItemDao orderItemDao = new OrderItemDao(conn);
            GoodsDao goodsDao = new GoodsDao(conn);
            
            for (CartItem item : cartItems) {
                OrderItem orderItem = new OrderItem();
                orderItem.setOrderId(orderId);
                orderItem.setGoodsId(item.getGoods().getId());
                orderItem.setPrice(item.getGoods().getPrice());
                orderItem.setAmount(item.getAmount());
                
                orderItemDao.addOrderItem(orderItem);
                goodsDao.updateStock(item.getGoods().getId(), -item.getAmount());
            }
            
            conn.commit();
            return true;
            
        } catch (SQLException e) {
            if (conn != null) {
                try { conn.rollback(); } catch (SQLException ex) {}
            }
            return false;
        } finally {
            DataBaseUtil.closeConnection(conn);
        }
    }
}

推荐系统实现

基于用户行为和商品属性的智能推荐算法:

public class RecommendService {
    public List<Goods> getRecommendGoods(int userId, int type, int limit) {
        List<Goods> recommendList = new ArrayList<>();
        
        // 基于协同过滤的推荐
        List<Goods> cfRecommend = getCFRecommend(userId, limit/2);
        recommendList.addAll(cfRecommend);
        
        // 基于内容的推荐
        List<Goods> contentRecommend = getContentRecommend(userId, limit - cfRecommend.size());
        recommendList.addAll(contentRecommend);
        
        // 热门商品补全
        if (recommendList.size() < limit) {
            List<Goods> hotGoods = getHotGoods(limit - recommendList.size());
            recommendList.addAll(hotGoods);
        }
        
        return recommendList;
    }
    
    private List<Goods> getCFRecommend(int userId, int limit) {
        // 实现基于用户的协同过滤算法
        String sql = """
            SELECT g.* FROM goods g 
            INNER JOIN orderitem oi ON g.id = oi.goods_id 
            INNER JOIN order o ON oi.order_id = o.id 
            WHERE o.user_id IN (
                SELECT DISTINCT o2.user_id FROM order o2 
                INNER JOIN orderitem oi2 ON o2.id = oi2.order_id 
                WHERE oi2.goods_id IN (
                    SELECT goods_id FROM orderitem oi3 
                    INNER JOIN order o3 ON oi3.order_id = o3.id 
                    WHERE o3.user_id = ?
                ) AND o2.user_id != ?
            ) AND g.id NOT IN (
                SELECT goods_id FROM orderitem oi4 
                INNER JOIN order o4 ON oi4.order_id = o4.id 
                WHERE o4.user_id = ?
            ) GROUP BY g.id ORDER BY COUNT(*) DESC LIMIT ?
            """;
        
        return goodsDao.query(sql, userId, userId, userId, limit);
    }
}

实体模型设计

系统采用面向对象的设计思想,核心实体模型体现了丰富的业务语义:

用户实体设计

public class User {
    private Integer id;
    private String username;
    private String email;
    private String password;
    private String name;
    private String phone;
    private String address;
    private Boolean isadmin;
    private Boolean isvalidate;
    
    // 构造方法、getter和setter
    public User() {}
    
    public User(String username, String email, String password) {
        this.username = username;
        this.email = email;
        this.password = password;
        this.isadmin = false;
        this.isvalidate = false;
    }
    
    // 业务方法
    public boolean validatePassword(String inputPassword) {
        return this.password.equals(MD5Util.md5(inputPassword));
    }
    
    public boolean canAccessAdmin() {
        return Boolean.TRUE.equals(isadmin) && Boolean.TRUE.equals(isvalidate);
    }
}

商品实体与值对象

public class Goods {
    private Integer id;
    private String name;
    private String cover;
    private String image1;
    private String image2;
    private Float price;
    private String intro;
    private Integer stock;
    private Integer typeId;
    private Type type; // 关联对象
    
    // 业务逻辑方法
    public boolean isAvailable() {
        return stock != null && stock > 0;
    }
    
    public boolean isOnSale() {
        return price != null && price > 0;
    }
    
    public String getMainImage() {
        return cover != null ? cover : (image1 != null ? image1 : image2);
    }
}

public class CartItem {
    private Goods goods;
    private Integer amount;
    private Float itemTotal;
    
    public CartItem(Goods goods, Integer amount) {
        this.goods = goods;
        this.amount = amount;
        this.itemTotal = goods.getPrice() * amount;
    }
    
    // 更新数量时的业务逻辑
    public void updateAmount(Integer newAmount) {
        this.amount = newAmount;
        this.itemTotal = goods.getPrice() * newAmount;
    }
}

功能展望与优化方向

性能优化方案

  1. 引入Redis缓存层:对热门商品数据、用户会话、页面片段进行缓存
@Component
public class GoodsCacheService {
    @Autowired
    private RedisTemplate<String, Goods> redisTemplate;
    
    public Goods getGoodsById(Integer id) {
        String key = "goods:" + id;
        Goods goods = redisTemplate.opsForValue().get(key);
        if (
本文关键词
JSPServlet游戏商城管理系统源码解析数据库设计

上下篇

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