SpringBoot+Vue3高校饮食推荐系统开发实践
2026/7/28 11:22:05 网站建设 项目流程

1. 项目概述

这个基于Java SpringBoot+Vue3+MyBatis的高校学生饮食推荐系统,是一个典型的前后端分离架构应用。系统通过分析学生的饮食偏好、消费习惯和营养需求,为高校学生提供个性化的餐饮推荐服务。我在开发过程中发现,这种系统不仅能帮助学生解决"今天吃什么"的难题,还能为食堂管理者提供数据支持,优化菜品供应结构。

系统采用MySQL作为数据库,充分发挥了SpringBoot的快速开发特性和Vue3的响应式优势。前后端分离的设计让开发和部署更加灵活,MyBatis作为ORM框架则简化了数据库操作。下面我将从技术选型、系统设计和实现细节三个方面,详细解析这个项目的开发过程。

2. 技术栈选型分析

2.1 后端技术选择

SpringBoot作为后端框架的选择主要基于以下几个考虑:

  1. 自动配置特性大幅减少了XML配置
  2. 内嵌Tomcat服务器简化了部署流程
  3. 丰富的starter依赖可以快速集成各种功能模块
  4. 完善的生态和社区支持

在实际开发中,我们特别使用了Spring Security进行权限控制,Spring Cache管理缓存,以及Spring Data JPA的部分特性辅助MyBatis。

2.2 前端框架考量

Vue3相比Vue2有几个显著优势:

  • Composition API提供了更好的代码组织方式
  • 更小的打包体积和更快的渲染速度
  • 更好的TypeScript支持
  • 更灵活的逻辑复用方式

我们特别利用了Vue3的setup语法糖、ref和reactive响应式API,以及Pinia状态管理库。Element Plus作为UI组件库,提供了丰富的预制组件。

2.3 数据库选型

MySQL 8.0作为关系型数据库的选择理由:

  • 高校饮食数据具有明确的结构化特征
  • 事务支持确保数据一致性
  • 成熟的索引机制优化查询性能
  • 丰富的社区资源和工具支持

我们在表设计时特别注意了范式化,同时针对热点查询做了适当的反范式优化。

3. 系统架构设计

3.1 整体架构

系统采用经典的三层架构:

  1. 表现层:Vue3前端应用
  2. 业务逻辑层:SpringBoot后端服务
  3. 数据访问层:MyBatis+MySQL

前后端通过RESTful API交互,使用JWT进行身份认证。特别设计了API网关统一处理跨域、鉴权和限流。

3.2 数据库设计

核心表包括:

  • 用户表(student_info)
  • 菜品表(dish_info)
  • 食堂表(canteen_info)
  • 消费记录表(consumption_record)
  • 评价表(rating)
  • 推荐记录表(recommendation)

我们建立了适当的索引和外键约束,同时使用触发器维护部分统计字段。

3.3 推荐算法设计

系统采用混合推荐策略:

  1. 基于内容的推荐:分析菜品特征相似度
  2. 协同过滤:根据相似用户的口味推荐
  3. 热门推荐:近期受欢迎的菜品
  4. 随机推荐:增加多样性

算法实现上使用了Java的Mahout库,并针对高校场景做了定制优化。

4. 关键功能实现

4.1 用户认证模块

采用JWT实现无状态认证:

// 生成Token示例 public String generateToken(UserDetails userDetails) { Map<String, Object> claims = new HashMap<>(); return Jwts.builder() .setClaims(claims) .setSubject(userDetails.getUsername()) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)) .signWith(SignatureAlgorithm.HS512, secret) .compact(); }

前端使用axios拦截器自动携带Token:

axios.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config })

4.2 推荐引擎实现

核心推荐逻辑:

public List<Dish> recommendDishes(Long studentId) { // 获取用户特征 StudentPreference preference = preferenceMapper.selectByStudentId(studentId); // 基于内容的推荐 List<Dish> contentBased = contentBasedRecommender.recommend(preference); // 协同过滤推荐 List<Dish> cfBased = cfRecommender.recommend(studentId); // 合并结果并去重 return mergeAndDeduplicate(contentBased, cfBased); }

4.3 前后端数据交互

典型API设计示例:

@RestController @RequestMapping("/api/dishes") public class DishController { @Autowired private DishService dishService; @GetMapping("/recommend") public ResponseEntity<List<DishDTO>> getRecommendations( @RequestParam Long studentId, @RequestParam(defaultValue = "10") int limit) { return ResponseEntity.ok(dishService.getRecommendations(studentId, limit)); } }

前端调用示例:

const fetchRecommendations = async (studentId) => { try { const res = await axios.get('/api/dishes/recommend', { params: { studentId } }); return res.data; } catch (error) { console.error('获取推荐失败:', error); return []; } }

5. 性能优化实践

5.1 数据库优化

  1. 索引优化:为常用查询字段建立复合索引
CREATE INDEX idx_dish_canteen ON dish_info(canteen_id, category);
  1. 查询优化:避免SELECT *,使用分页
@Select("SELECT id, name, price FROM dish_info WHERE canteen_id = #{canteenId} LIMIT #{offset}, #{limit}") List<Dish> selectByCanteen(@Param("canteenId") Long canteenId, @Param("offset") int offset, @Param("limit") int limit);
  1. 缓存策略:使用Redis缓存热点数据

5.2 前端性能优化

  1. 组件懒加载:
const RecommendList = defineAsyncComponent(() => import('./components/RecommendList.vue') )
  1. 图片懒加载:
<img v-lazy="dish.imageUrl" alt="菜品图片">
  1. API请求合并与防抖

5.3 推荐算法优化

  1. 离线计算:定时任务预先计算推荐结果
  2. 增量更新:用户行为实时更新推荐模型
  3. 结果缓存:缓存推荐结果减少重复计算

6. 安全防护措施

6.1 SQL注入防护

MyBatis严格使用#{}参数绑定:

<select id="selectByConditions" resultType="Dish"> SELECT * FROM dish_info WHERE name LIKE CONCAT('%', #{name}, '%') AND price BETWEEN #{minPrice} AND #{maxPrice} </select>

6.2 XSS防护

前端使用DOMPurify净化输入:

import DOMPurify from 'dompurify'; const clean = DOMPurify.sanitize(userInput);

后端统一过滤敏感字符:

public String filterXSS(String value) { if (value == null) return null; return value.replaceAll("<", "&lt;") .replaceAll(">", "&gt;"); }

6.3 CSRF防护

虽然使用JWT后CSRF风险降低,但仍采取了以下措施:

  1. 关键操作需要二次确认
  2. 敏感接口使用POST而非GET
  3. 设置SameSite cookie属性

7. 部署与监控

7.1 多环境配置

SpringBoot profiles配置不同环境:

# application-dev.yml server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/campus_food_dev

7.2 容器化部署

使用Docker编排:

# 后端Dockerfile示例 FROM openjdk:11 COPY target/campus-food.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]

7.3 监控方案

  1. Spring Boot Actuator提供健康检查
  2. Prometheus + Grafana监控系统指标
  3. ELK日志收集分析

8. 开发中的经验总结

8.1 前后端协作经验

  1. 使用Swagger维护API文档
  2. 定义统一的响应格式
{ "code": 200, "message": "success", "data": {} }
  1. 约定错误代码规范

8.2 性能调优心得

  1. 数据库查询N+1问题解决:
// 使用MyBatis的@SelectProvider实现联合查询 @SelectProvider(type = DishSqlProvider.class, method = "selectWithCanteen") List<DishWithCanteen> selectWithCanteen();
  1. Vue组件性能优化:
  • 合理使用v-if和v-show
  • 避免不必要的响应式数据
  • 使用computed缓存计算结果

8.3 推荐算法改进方向

  1. 引入时间因素:考虑早中晚餐不同需求
  2. 天气影响:不同天气推荐不同菜品
  3. 社交因素:好友喜欢的菜品加权推荐

9. 常见问题解决方案

9.1 跨域问题

SpringBoot配置CORS:

@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*"); } }

9.2 页面刷新404

Vue Router配置:

const router = createRouter({ history: createWebHistory(), routes, }) // 后端需要配置所有路由指向index.html

9.3 MyBatis动态SQL

使用

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询