基于SSH框架的在线外卖订餐系统 - 源码深度解析

JavaJavaScriptSSH框架HTMLCSSMySQLJSP+Servlet
2026-02-1011 浏览

文章摘要

基于SSH框架的在线外卖订餐系统是一个整合了Struts2、Spring和Hibernate技术的企业级Java Web应用。该系统旨在为餐饮商家提供一个功能完整、稳定可靠的在线销售平台,其核心业务价值在于将传统的电话订餐流程数字化、自动化,有效解决了餐饮行业在高峰期订单处理效率低下、人工记录易出错...

在餐饮行业数字化转型的浪潮中,一套高效、稳定的在线订餐平台成为餐饮商家提升运营效率、优化顾客体验的关键工具。本文介绍的企业级外卖管理平台,采用经典的SSH(Struts2 + Spring + Hibernate)框架技术栈,实现了从菜单展示、在线下单到订单管理的全流程自动化处理。

系统架构与技术栈

该平台采用典型的三层架构设计,各层职责分明,实现了高内聚低耦合的软件工程原则。

表现层基于Struts2框架构建,通过配置struts.xml文件定义请求路由,Action类负责接收前端参数并调用业务逻辑。Struts2的拦截器机制提供了统一的权限验证、数据校验等功能。

<!-- struts.xml 配置示例 -->
<struts>
    <package name="food" extends="struts-default">
        <action name="goods_*" class="goodsAction" method="{1}">
            <result name="success">/goods_{1}.jsp</result>
        </action>
        <action name="order_*" class="orderAction" method="{1}">
            <result name="success">/order_{1}.jsp</result>
        </action>
    </package>
</struts>

业务逻辑层由Spring框架托管,通过IoC容器管理Bean的生命周期和依赖关系。@Service注解标识的业务组件处理核心业务规则,并通过@Transactional注解实现声明式事务管理。

@Service("orderService")
@Transactional
public class OrderServiceImpl implements OrderService {
    
    @Autowired
    private OrderDAO orderDAO;
    
    @Autowired
    private GoodsDAO goodsDAO;
    
    @Override
    public void createOrder(Order order, List<OrderItem> items) {
        // 保存订单主信息
        orderDAO.save(order);
        
        // 保存订单明细并更新库存
        for (OrderItem item : items) {
            orderDAO.saveItem(item);
            goodsDAO.updateStock(item.getGoods_id(), 
                               -item.getGoods_quantity());
        }
    }
}

数据持久层采用Hibernate实现ORM映射,实体类通过注解方式定义与数据库表的对应关系,DAO层使用HibernateTemplate简化数据库操作。

@Entity
@Table(name = "t_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer order_id;
    
    private String order_bianhao;
    private String order_date;
    private String order_zhuangtai;
    private String order_songhuodizhi;
    private String order_fukuangfangshi;
    private Integer order_jine;
    private Integer order_user_id;
    
    // 一对多关联订单项
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private Set<OrderItem> orderItems = new HashSet<>();
    
    // getter/setter方法
}

数据库设计亮点分析

订单模块的规范化设计

订单表(t_order)和订单项表(t_orderitem)的设计体现了良好的数据库规范化原则。订单表存储订单的核心信息,而订单项表通过order_id外键关联,实现了一对多的关系映射。

-- 订单表核心字段设计
CREATE TABLE `t_order` (
  `order_id` int(11) NOT NULL COMMENT '订单ID',
  `order_bianhao` varchar(50) DEFAULT NULL COMMENT '订单编号',
  `order_date` varchar(50) DEFAULT NULL COMMENT '订单日期',
  `order_zhuangtai` varchar(50) DEFAULT NULL COMMENT '订单状态',
  `order_songhuodizhi` varchar(50) DEFAULT NULL COMMENT '送货地址',
  `order_fukuangfangshi` varchar(50) DEFAULT NULL COMMENT '付款方式',
  `order_jine` int(11) DEFAULT NULL COMMENT '订单金额',
  `order_user_id` int(11) DEFAULT NULL COMMENT '用户ID',
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 订单项表设计,支持一个订单多个商品
CREATE TABLE `t_orderitem` (
  `orderItem_id` int(11) NOT NULL COMMENT '订单项ID',
  `order_id` int(11) DEFAULT NULL COMMENT '订单ID',
  `goods_id` int(11) DEFAULT NULL COMMENT '商品ID',
  `goods_quantity` int(11) DEFAULT NULL COMMENT '商品数量',
  PRIMARY KEY (`orderItem_id`),
  KEY `fk_order` (`order_id`),
  KEY `fk_goods` (`goods_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这种分离设计的好处在于:

  • 数据一致性:订单总金额通过应用程序计算确保准确
  • 扩展性:轻松支持订单中包含多个不同商品
  • 查询效率:通过索引优化关联查询性能

商品信息管理的完整性约束

商品表(t_goods)的设计考虑了电商平台的完整需求,包含了价格策略、库存管理、分类体系等核心业务字段。

CREATE TABLE `t_goods` (
  `goods_id` int(11) NOT NULL COMMENT '商品ID',
  `goods_name` varchar(50) DEFAULT NULL COMMENT '商品名称',
  `goods_miaoshu` text DEFAULT NULL COMMENT '商品描述',
  `goods_pic` varchar(50) DEFAULT NULL COMMENT '商品图片',
  `goods_ISBN` varchar(50) DEFAULT NULL COMMENT '商品ISBN',
  `goods_shichangjia` int(11) DEFAULT NULL COMMENT '商品市场价',
  `goods_tejia` int(11) DEFAULT NULL COMMENT '商品特价',
  `goods_isnottejia` varchar(50) DEFAULT NULL COMMENT '是否特价',
  `goods_isnottuijian` varchar(50) DEFAULT NULL COMMENT '是否推荐',
  `goods_catelog_id` int(11) DEFAULT NULL COMMENT '商品分类ID',
  `goods_kucun` int(11) DEFAULT NULL COMMENT '商品库存',
  `goods_Del` varchar(50) DEFAULT NULL COMMENT '删除标记',
  PRIMARY KEY (`goods_id`),
  KEY `idx_catelog` (`goods_catelog_id`),
  KEY `idx_tejia` (`goods_isnottejia`),
  KEY `idx_tuijian` (`goods_isnottuijian`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

索引策略分析:

  • 分类索引(idx_catelog):加速按分类筛选商品的查询
  • 特价商品索引(idx_tejia):快速定位促销商品
  • 推荐商品索引(idx_tuijian):优化首页推荐商品的加载速度

核心功能实现详解

购物车与订单生成机制

购物车功能采用Session临时存储的方式,用户在浏览商品过程中可以随时添加商品到购物车。系统通过Struts2 Action处理添加请求,并维护购物车商品列表。

public class CartAction extends ActionSupport {
    private List<CartItem> cartItems;
    private Integer goodsId;
    private Integer quantity;
    
    // 添加商品到购物车
    public String addToCart() {
        Goods goods = goodsService.getGoodsById(goodsId);
        CartItem item = new CartItem(goods, quantity);
        
        // 从Session获取当前购物车
        Map<Integer, CartItem> cart = getCartFromSession();
        if (cart.containsKey(goodsId)) {
            // 更新数量
            CartItem existing = cart.get(goodsId);
            existing.setQuantity(existing.getQuantity() + quantity);
        } else {
            cart.put(goodsId, item);
        }
        
        return SUCCESS;
    }
    
    // 生成订单
    public String createOrder() {
        Order order = new Order();
        order.setOrder_bianhao(generateOrderNumber());
        order.setOrder_date(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        order.setOrder_zhuangtai("待处理");
        order.setOrder_jine(calculateTotalAmount());
        
        List<OrderItem> orderItems = convertCartToOrderItems();
        orderService.createOrder(order, orderItems);
        
        // 清空购物车
        clearCart();
        
        return SUCCESS;
    }
}

购物车页面

多维度商品管理后台

管理员后台提供了完整的商品生命周期管理功能,包括商品上架、信息修改、价格调整、库存管理等。

@Service("goodsService")
public class GoodsServiceImpl implements GoodsService {
    
    @Override
    public void addGoods(Goods goods) {
        // 验证数据完整性
        validateGoodsInfo(goods);
        
        // 设置默认值
        if (goods.getGoods_kucun() == null) {
            goods.setGoods_kucun(0);
        }
        if (goods.getGoods_Del() == null) {
            goods.setGoods_Del("否");
        }
        
        goodsDAO.save(goods);
    }
    
    @Override
    public PageBean<Goods> getGoodsByPage(int page, int pageSize, 
                                         Map<String, Object> params) {
        // 构建查询条件
        DetachedCriteria criteria = DetachedCriteria.forClass(Goods.class);
        
        if (params.containsKey("catelogId")) {
            criteria.add(Restrictions.eq("goods_catelog_id", 
                        params.get("catelogId")));
        }
        if (params.containsKey("isTejia")) {
            criteria.add(Restrictions.eq("goods_isnottejia", 
                        params.get("isTejia")));
        }
        
        // 执行分页查询
        return goodsDAO.findByPage(criteria, page, pageSize);
    }
    
    @Override
    @Transactional
    public void updateGoodsStock(Integer goodsId, Integer quantity) {
        Goods goods = goodsDAO.findById(goodsId);
        if (goods != null) {
            int newStock = goods.getGoods_kucun() + quantity;
            if (newStock < 0) {
                throw new RuntimeException("库存不足");
            }
            goods.setGoods_kucun(newStock);
            goodsDAO.update(goods);
        }
    }
}

菜品管理后台

订单状态流转与跟踪

系统实现了完整的订单状态机,从"待处理"到"制作中"、"已送出"、"已完成"等状态流转,每个状态变更都记录相应的时间戳和操作人。

@Entity
@Table(name = "t_order")
public class Order {
    // ... 其他字段
    
    /**
     * 订单状态流转处理
     */
    public void changeStatus(String newStatus, String operator) {
        // 验证状态流转合法性
        if (!isValidStatusTransition(this.order_zhuangtai, newStatus)) {
            throw new IllegalStateException("无效的状态流转: " 
                + this.order_zhuangtai + " -> " + newStatus);
        }
        
        this.order_zhuangtai = newStatus;
        // 记录状态变更日志
        addStatusLog(newStatus, operator);
    }
    
    private boolean isValidStatusTransition(String from, String to) {
        Map<String, List<String>> validTransitions = new HashMap<>();
        validTransitions.put("待处理", Arrays.asList("制作中", "已取消"));
        validTransitions.put("制作中", Arrays.asList("已送出", "已取消"));
        validTransitions.put("已送出", Arrays.asList("已完成"));
        
        return validTransitions.containsKey(from) 
            && validTransitions.get(from).contains(to);
    }
}

订单管理界面

用户权限管理与安全控制

系统采用基于角色的访问控制(RBAC)模型,区分普通用户和管理员两种角色,通过拦截器实现统一的权限验证。

<!-- Spring Security 配置示例 -->
<beans:bean id="securityFilter" class="com.xxx.util.SecurityInterceptor">
    <beans:property name="excludeActions">
        <beans:list>
            <beans:value>user_login</beans:value>
            <beans:value>goods_list</beans:value>
            <beans:value>index_*</beans:value>
        </beans:list>
    </beans:property>
</beans:bean>
public class SecurityInterceptor extends AbstractInterceptor {
    
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        ActionContext context = invocation.getInvocationContext();
        Map<String, Object> session = context.getSession();
        
        // 检查排除列表
        String actionName = invocation.getProxy().getActionName();
        if (isExcludedAction(actionName)) {
            return invocation.invoke();
        }
        
        // 验证用户登录状态
        User user = (User) session.get("currentUser");
        if (user == null) {
            return "login"; // 跳转到登录页面
        }
        
        // 管理员权限验证
        if (actionName.startsWith("admin_") && !user.isAdmin()) {
            return "accessDenied";
        }
        
        return invocation.invoke();
    }
}

用户登录界面

实体模型设计精要

系统的实体模型设计充分体现了领域驱动设计(DDD)的思想,每个实体都封装了相应的业务逻辑和行为。

订单聚合根设计

Order作为订单聚合的根实体,负责维护订单项的一致性边界和业务规则。

@Entity
@Table(name = "t_order")
public class Order {
    
    /**
     * 计算订单总金额
     */
    public void calculateTotalAmount() {
        this.order_jine = 0;
        for (OrderItem item : orderItems) {
            Goods goods = item.getGoods();
            int price = "是".equals(goods.getGoods_isnottejia()) 
                ? goods.getGoods_tejia() : goods.getGoods_shichangjia();
            this.order_jine += price * item.getGoods_quantity();
        }
    }
    
    /**
     * 验证订单完整性
     */
    public void validate() {
        if (orderItems == null || orderItems.isEmpty()) {
            throw new IllegalArgumentException("订单必须包含至少一个商品");
        }
        
        for (OrderItem item : orderItems) {
            if (item.getGoods_quantity() <= 0) {
                throw new IllegalArgumentException("商品数量必须大于0");
            }
            
            // 检查库存
            if (item.getGoods().getGoods_kucun() < item.getGoods_quantity()) {
                throw new IllegalArgumentException(
                    "商品[" + item.getGoods().getGoods_name() + "]库存不足");
            }
        }
    }
}

商品值对象与业务逻辑

Goods实体不仅包含基本属性,还封装了价格计算、库存检查等业务方法。

@Entity
@Table(name = "t_goods")
public class Goods {
    
    /**
     * 获取当前有效价格
     */
    public Integer getCurrentPrice() {
        return "是".equals(goods_isnottejia) ? goods_tejia : goods_shichangjia;
    }
    
    /**
     * 检查库存是否充足
     */
    public boolean isStockSufficient(Integer requiredQuantity) {
        return goods_kucun != null && goods_kucun >= requiredQuantity;
    }
    
    /**
     * 减少库存
     */
    public void reduceStock(Integer quantity) {
        if (!isStockSufficient(quantity)) {
            throw new IllegalArgumentException("库存不足");
        }
        this.goods_kucun -= quantity;
    }
}

功能展望与系统优化方向

性能优化与缓存策略

当前系统在高并发场景下可能存在性能瓶颈,未来可以考虑引入Redis缓存层来提升系统响应速度。

@Service
public class GoodsServiceWithCache {
    
    @Autowired
    private RedisTemplate<String, Goods> redisTemplate;
    
    private static final String GOODS_KEY_PREFIX = "goods:";
    private static final long CACHE_EXPIRE_HOURS = 24;
    
    public Goods getGoodsByIdWithCache(Integer goodsId) {
        String cacheKey = GOODS_KEY_PREFIX + goodsId;
        
        // 先查缓存
        Goods goods = redisTemplate.opsForValue().get(cacheKey);
        if (goods != null) {
            return goods;
        }
        
        // 缓存未命中,查询数据库
        goods = goodsDAO.findById(goodsId);
        if (goods != null) {
            // 写入缓存
            redisTemplate.opsForValue().set(cacheKey, goods, 
                CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
        }
        
        return goods;
    }
}

微服务架构改造

随着业务规模扩大,可以将单体应用拆分为多个微服务,如用户服务、商品服务、订单服务等,提高系统的可维护性和扩展性。

# Spring Cloud 微服务配置示例
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    loadbalancer:
      enabled: true

server:
  port: 8081

# Feign客户端配置
feign:
  client:
    config:
      user-service:
        connectTimeout: 5000
        readTimeout: 5000

移动端适配与PWA技术

开发响应式前端界面,并引入PWA(渐进式Web应用)技术,使系统在移动设备上具备原生应用的体验。

// Service Worker 缓存策略
self.addEventListener('install', event => {
    event.waitUntil(
        caches.open('food-delivery-v1').then(cache => {
            return cache.addAll([
                '/',
                '/static/css/main.css',
                '/static/js/app.js',
                '/static/images/logo.png'
            ]);
        })
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            return response || fetch(event.request);
        })
    );
});

智能推荐与数据分析

基于用户历史订单数据,构建推荐算法模型,实现个性化菜品推荐,提升用户粘性和订单转化率。

# 基于协同过滤的推荐算法示例
from sklearn.metrics.pairwise import cosine_similarity
import pandas as pd

def recommend_items(user_id, user_item
本文关键词
SSH框架在线外卖系统订餐系统源码解析系统架构

上下篇

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