基于SSM框架的智能点餐推荐系统 - 源码深度解析

JavaJavaScriptMavenHTMLCSSSSM框架MySQL
2026-02-195 浏览

文章摘要

本系统是基于SSM(Spring+Spring MVC+MyBatis)框架构建的智能点餐推荐平台,旨在解决传统餐饮服务中顾客选择困难、菜品信息不透明以及商家营销效率低下的核心痛点。系统通过分析用户的点餐历史、口味偏好及实时浏览行为,运用智能算法为每位顾客生成个性化的菜品推荐,从而有效缩短决策时间、...

在当今快节奏的餐饮服务行业中,顾客面对繁杂的菜单常常陷入选择困难,而商家也面临着如何精准营销、提升客户满意度的挑战。针对这些痛点,一个基于SSM(Spring+Spring MVC+MyBatis)框架的智慧餐饮决策平台应运而生。该系统通过整合用户行为分析、智能推荐算法和高效的Web服务架构,为餐饮业务的数字化转型提供了强有力的技术支撑。

平台采用经典的三层架构模式。Spring框架作为核心控制容器,管理着所有业务对象的生命周期和依赖关系,其声明式事务管理机制确保了订单处理、用户积分变更等关键操作的数据一致性。Spring MVC模块负责Web请求的调度与控制,通过精心设计的拦截器实现用户权限验证和系统操作日志记录。数据持久层由MyBatis实现,利用其灵活的XML映射配置和动态SQL能力,高效地处理用户、菜品、订单等复杂的数据关联查询。

数据库设计是系统稳定运行的基石。整个平台共设计12张数据表,其中用户表(user)采用纵向分表设计,将基础信息与隐私数据分离存储。核心的菜品表(dish)结构设计颇具亮点:

CREATE TABLE `dish` (
  `dish_id` int(11) NOT NULL AUTO_INCREMENT,
  `category_id` int(11) NOT NULL,
  `dish_name` varchar(100) NOT NULL,
  `price` decimal(10,2) NOT NULL,
  `description` text,
  `image_url` varchar(255) DEFAULT NULL,
  `stock_quantity` int(11) DEFAULT '0',
  `sales_count` int(11) DEFAULT '0',
  `is_recommended` tinyint(1) DEFAULT '0',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`dish_id`),
  KEY `idx_category` (`category_id`),
  KEY `idx_sales` (`sales_count`),
  KEY `idx_recommended` (`is_recommended`),
  CONSTRAINT `fk_dish_category` FOREIGN KEY (`category_id`) REFERENCES `category` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

该表通过多维度索引优化查询性能,sales_count字段实时统计菜品销量,为推荐算法提供数据支持。is_recommended标志位允许管理员手动设置推荐菜品,与智能推荐结果形成互补。

订单表(order)的设计同样体现了业务复杂性:

CREATE TABLE `order` (
  `order_id` varchar(32) NOT NULL,
  `user_id` int(11) NOT NULL,
  `total_amount` decimal(10,2) NOT NULL,
  `status` enum('pending','confirmed','preparing','delivering','completed','cancelled') DEFAULT 'pending',
  `payment_status` enum('unpaid','paid','refunded') DEFAULT 'unpaid',
  `delivery_address` text,
  `contact_phone` varchar(20) DEFAULT NULL,
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`order_id`),
  KEY `idx_user` (`user_id`),
  KEY `idx_status` (`status`),
  KEY `idx_create_time` (`create_time`),
  CONSTRAINT `fk_order_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

采用字符串类型的订单ID便于分布式环境下的唯一性保证,枚举类型的状态字段确保业务逻辑的严谨性,多时间戳字段为数据分析和报表生成提供完整的时间维度。

智能推荐功能是平台的核心竞争力。推荐算法服务被封装为独立的Java组件,基于用户的历史订单和实时浏览行为进行计算:

@Service
public class RecommendationService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private DishMapper dishMapper;
    
    public List<Dish> getPersonalizedRecommendations(Integer userId) {
        // 获取用户最近订单中的菜品
        List<OrderItem> recentOrders = orderMapper.selectRecentOrdersByUserId(userId, 10);
        Map<Integer, Integer> dishFrequency = new HashMap<>();
        
        for (OrderItem item : recentOrders) {
            dishFrequency.put(item.getDishId(), 
                dishFrequency.getOrDefault(item.getDishId(), 0) + 1);
        }
        
        // 基于协同过滤的简单实现
        List<Integer> similarUsers = findSimilarUsers(userId);
        List<Dish> recommendedDishes = new ArrayList<>();
        
        for (Integer similarUserId : similarUsers) {
            List<OrderItem> similarUserOrders = orderMapper
                .selectRecentOrdersByUserId(similarUserId, 5);
            for (OrderItem item : similarUserOrders) {
                if (!dishFrequency.containsKey(item.getDishId())) {
                    Dish dish = dishMapper.selectByPrimaryKey(item.getDishId());
                    if (dish != null && dish.getStockQuantity() > 0) {
                        recommendedDishes.add(dish);
                    }
                }
            }
        }
        
        return recommendedDishes.stream()
                .distinct()
                .limit(6)
                .collect(Collectors.toList());
    }
    
    private List<Integer> findSimilarUsers(Integer userId) {
        // 简化实现:返回最近活跃的用户
        return orderMapper.selectRecentActiveUsers(20);
    }
}

用户界面设计注重用户体验。主页采用响应式布局,智能推荐菜品以瀑布流形式展示:

智能推荐主页

购物车功能实现完整的商品管理流程:

@Controller
@RequestMapping("/cart")
public class CartController {
    
    @Autowired
    private CartService cartService;
    
    @PostMapping("/add")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> addToCart(
            @RequestParam Integer dishId,
            @RequestParam Integer quantity,
            HttpSession session) {
        Integer userId = (Integer) session.getAttribute("userId");
        if (userId == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }
        
        try {
            cartService.addItemToCart(userId, dishId, quantity);
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("message", "商品已成功加入购物车");
            return ResponseEntity.ok(result);
        } catch (BusinessException e) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", e.getMessage());
            return ResponseEntity.badRequest().body(result);
        }
    }
    
    @GetMapping("/view")
    public String viewCart(Model model, HttpSession session) {
        Integer userId = (Integer) session.getAttribute("userId");
        List<CartItem> cartItems = cartService.getCartItems(userId);
        model.addAttribute("cartItems", cartItems);
        return "cart/view";
    }
}

购物车界面清晰展示商品信息、数量和总价:

购物车管理

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

@Service
public class OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private OrderItemMapper orderItemMapper;
    
    @Transactional
    public String createOrder(OrderDTO orderDTO) {
        // 生成订单号
        String orderId = generateOrderId();
        
        Order order = new Order();
        order.setOrderId(orderId);
        order.setUserId(orderDTO.getUserId());
        order.setTotalAmount(calculateTotalAmount(orderDTO.getItems()));
        order.setDeliveryAddress(orderDTO.getDeliveryAddress());
        order.setContactPhone(orderDTO.getContactPhone());
        
        orderMapper.insert(order);
        
        for (OrderItemDTO itemDTO : orderDTO.getItems()) {
            OrderItem item = new OrderItem();
            item.setOrderId(orderId);
            item.setDishId(itemDTO.getDishId());
            item.setQuantity(itemDTO.getQuantity());
            item.setUnitPrice(itemDTO.getUnitPrice());
            orderItemMapper.insert(item);
        }
        
        return orderId;
    }
    
    private String generateOrderId() {
        return "ORD" + System.currentTimeMillis() + 
               String.format("%04d", new Random().nextInt(10000));
    }
}

订单提交界面提供完整的订单信息确认:

订单提交

后台管理系统提供全面的数据管理功能。菜品管理模块支持分类、上传、库存调整等操作:

@Controller
@RequestMapping("/admin/dish")
public class AdminDishController {
    
    @Autowired
    private DishService dishService;
    
    @PostMapping("/upload")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> uploadDishImage(
            @RequestParam("file") MultipartFile file) {
        try {
            String imageUrl = dishService.saveDishImage(file);
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("imageUrl", imageUrl);
            return ResponseEntity.ok(result);
        } catch (IOException e) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "图片上传失败");
            return ResponseEntity.badRequest().body(result);
        }
    }
    
    @PostMapping("/update")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> updateDish(@RequestBody Dish dish) {
        try {
            dishService.updateDish(dish);
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("message", "菜品更新成功");
            return ResponseEntity.ok(result);
        } catch (BusinessException e) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", e.getMessage());
            return ResponseEntity.badRequest().body(result);
        }
    }
}

后台菜品管理界面功能完善:

菜品管理

用户个人中心提供完整的个人信息管理功能:

个人资料更新

系统在性能优化方面采取多项措施。MyBatis的二级缓存被配置用于缓存频繁访问的菜品分类数据和推荐结果:

<!-- MyBatis映射文件配置 -->
<mapper namespace="com.restaurant.mapper.DishMapper">
    <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
    
    <select id="selectRecommendedDishes" resultType="Dish" useCache="true">
        SELECT * FROM dish 
        WHERE is_recommended = 1 
        AND stock_quantity > 0 
        ORDER BY sales_count DESC 
        LIMIT 10
    </select>
    
    <select id="selectByCategory" parameterType="int" resultType="Dish">
        SELECT * FROM dish 
        WHERE category_id = #{categoryId} 
        AND stock_quantity > 0 
        ORDER BY create_time DESC
    </select>
</mapper>

数据库连接池配置优化:

# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/restaurant_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.max-lifetime=1200000

系统日志记录采用AOP实现,统一处理操作日志:

@Aspect
@Component
public class LogAspect {
    
    @Autowired
    private SystemLogMapper systemLogMapper;
    
    @Pointcut("execution(* com.restaurant.controller..*.*(..))")
    public void controllerPointcut() {}
    
    @AfterReturning(pointcut = "controllerPointcut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        
        SystemLog log = new SystemLog();
        log.setModule(className);
        log.setOperation(methodName);
        log.setCreateTime(new Date());
        
        // 从Session获取当前用户
        HttpServletRequest request = ((ServletRequestAttributes) 
            RequestContextHolder.getRequestAttributes()).getRequest();
        Integer userId = (Integer) request.getSession().getAttribute("userId");
        log.setUserId(userId);
        
        systemLogMapper.insert(log);
    }
}

日志管理界面提供完整的系统操作追踪:

系统日志

在安全性方面,系统采用多层级防护措施。密码使用BCrypt强哈希算法加密存储:

@Service
public class SecurityService {
    
    public String encryptPassword(String rawPassword) {
        return BCrypt.hashpw(rawPassword, BCrypt.gensalt(12));
    }
    
    public boolean checkPassword(String rawPassword, String encryptedPassword) {
        return BCrypt.checkpw(rawPassword, encryptedPassword);
    }
}

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

@Component
public class AuthInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        
        // 公开接口放行
        if (requestURI.contains("/public/") || 
            requestURI.contains("/login") ||
            requestURI.contains("/register")) {
            return true;
        }
        
        HttpSession session = request.getSession();
        Integer userId = (Integer) session.getAttribute("userId");
        String userRole = (String) session.getAttribute("userRole");
        
        if (userId == null) {
            response.sendRedirect("/user/login");
            return false;
        }
        
        // 管理员接口权限验证
        if (requestURI.contains("/admin/") && !"admin".equals(userRole)) {
            response.sendError(HttpStatus.FORBIDDEN.value(), "权限不足");
            return false;
        }
        
        return true;
    }
}

系统具备良好的扩展性架构。通过接口抽象和依赖注入,核心业务组件可以轻松替换或扩展。未来可从以下几个方向进行功能增强:

推荐算法优化方面,可引入机器学习模型,基于用户的长短期偏好进行更精准的预测。实现思路包括收集更丰富的用户行为数据,使用TensorFlow Serving部署推荐模型,通过gRPC接口与现有系统集成。

移动端适配值得重点投入,开发React Native或Flutter跨平台应用。技术实现上可基于现有RESTful API构建,采用JWT令牌替代Session进行身份认证,支持离线点餐和推送通知功能。

实时数据分析平台能显著提升商业价值。集成Apache Kafka处理用户行为数据流,使用Apache Flink进行实时计算,在Elasticsearch中构建业务指标看板,为运营决策提供数据支持。

供应链管理扩展将形成完整闭环。新增供应商管理、库存预警、采购订单等模块,与现有菜品管理深度集成,实现从原料到餐桌的全流程数字化管理。

多餐厅连锁支持是规模化发展的关键。通过租户隔离设计,支持同一平台服务多个餐厅品牌,每个租户拥有独立的数据空间和定制化界面,同时共享底层的技术基础设施。

系统通过严谨的架构设计、可靠的技术选型和周到的用户体验考量,为餐饮行业提供了一个功能完善、性能稳定、易于扩展的数字化解决方案。其模块化设计和清晰的代码结构为后续的功能迭代和技术升级奠定了坚实基础。

本文关键词
SSM框架智能点餐推荐系统源码解析餐饮系统

上下篇

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