1. 项目背景与核心需求
校园食堂作为师生日常高频使用的场所,其运营效率直接影响着用餐体验。传统窗口排队模式在用餐高峰期常出现以下痛点:
- 排队时间长导致就餐时间集中
- 人工结算效率低下易出错
- 菜品销售数据统计滞后
- 库存管理依赖经验预估
我们开发的SpringBoot+Vue全栈系统正是针对这些痛点设计的数字化解决方案。前端采用Vue3+Element Plus构建响应式界面,后端基于SpringBoot 2.7提供RESTful API,通过MySQL进行数据持久化,并集成ECharts实现数据可视化。
实际开发中发现,校园场景对系统有特殊要求:必须支持瞬时高并发(如上午第四节课结束时的点餐高峰),且需要兼容校园网弱网环境。
2. 技术架构设计
2.1 前后端分离架构
采用经典的三层架构设计:
code复制客户端层:Vue3 + Vite + Pinia
应用层:SpringBoot + Spring Security + JWT
数据层:MySQL + Redis(缓存)
选择Vue3而非Vue2的主要考虑:
- Composition API更适合复杂业务逻辑组织
- 更好的TypeScript支持
- 更小的打包体积(对校园网环境友好)
2.2 关键通信设计
java复制// 示例:JWT鉴权拦截器
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String token = request.getHeader("Authorization");
// 验证token逻辑
if(!JwtUtil.verify(token)){
throw new AuthException("无效token");
}
return true;
}
}
特别注意:校园环境下设备多样性要求接口必须做好兼容处理。我们遇到过的典型问题包括:
- 部分老旧Android设备无法解析JSON大整数(需配置Jackson的String序列化)
- iOS Safari浏览器对CORS预检请求的特殊处理
3. 核心功能实现
3.1 智能点餐流程
采用购物车模式设计订单创建流程:
- 菜品展示使用虚拟滚动技术(vue-virtual-scroller)优化万级商品列表渲染
- 实时库存检查通过WebSocket推送更新
- 优惠计算采用策略模式实现:
typescript复制// 优惠策略接口
interface DiscountStrategy {
calculate(originalPrice: number): number;
}
// 满减策略实现
class FullReductionStrategy implements DiscountStrategy {
calculate(price: number) {
return price >= 100 ? price - 20 : price;
}
}
3.2 订单状态机设计
使用状态模式管理订单生命周期:
java复制public enum OrderStatus {
CREATED(1, "已创建"),
PAID(2, "已支付"),
PREPARING(3, "制作中"),
DELIVERED(4, "待取餐"),
COMPLETED(5, "已完成"),
CANCELLED(-1, "已取消");
// 状态转换校验逻辑
public static boolean canTransfer(OrderStatus from, OrderStatus to) {
// 具体校验规则...
}
}
实测中发现需要特别注意:
- 支付超时自动取消(使用Spring的@Scheduled实现)
- 取餐码防冲突(采用Redis原子操作生成)
4. 数据分析模块
4.1 实时看板设计
使用ECharts实现的关键指标:
- 热力图展示各时段人流量
- 雷达图分析菜品营养结构
- 漏斗图追踪订单转化率
vue复制<template>
<div ref="chart" style="width:600px;height:400px"></div>
</template>
<script setup>
import * as echarts from 'echarts';
import { onMounted, ref } from 'vue';
const chart = ref(null);
onMounted(() => {
const instance = echarts.init(chart.value);
instance.setOption({
tooltip: { trigger: 'axis' },
xAxis: { data: ['周一','周二','周三'] },
series: [{ data: [120,200,150], type: 'line' }]
});
});
</script>
4.2 离线分析任务
使用Spring Batch处理每日统计:
- 凌晨2点触发定时任务
- 计算各窗口单位时间接待量
- 生成菜品销售关联规则(Apriori算法)
- 预测次日食材需求量(线性回归)
踩坑记录:最初使用MySQL直接计算关联规则导致全表锁死,后改为先将数据导出到Redis再计算。
5. 性能优化实践
5.1 前端优化措施
- 图片懒加载:对菜品图片使用Intersection Observer API
- API请求合并:将多个商品详情请求合并为批量查询
- 本地缓存策略:对静态菜单数据使用localStorage缓存
5.2 后端优化方案
java复制// 使用Spring Cache注解缓存热点数据
@Cacheable(value = "popularFoods", key = "#canteenId")
public List<Food> getPopularFoods(Long canteenId) {
// 查询逻辑...
}
// 二级缓存配置
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new RedisCacheManager(
RedisCacheWriter.lockingRedisCacheWriter(redisConnectionFactory),
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30))
);
}
}
实测性能对比:
| 场景 | 优化前QPS | 优化后QPS |
|---|---|---|
| 菜单查询 | 120 | 2100 |
| 订单提交 | 85 | 680 |
6. 安全防护策略
6.1 常见攻击防护
- XSS防御:前端使用DOMPurify过滤富文本
- CSRF防护:Spring Security默认启用防护
- SQL注入:全程使用JPA/Hibernate参数化查询
- 数据脱敏:对手机号等敏感字段使用@JsonSerialize注解
6.2 校园特殊场景
- 防刷单:同一学号5分钟内限购3单(Redis计数器实现)
- 防代充:人脸识别取餐(对接学校统一身份认证)
- 防作弊:订单修改留痕(使用Hibernate Envers审计)
7. 部署实践
7.1 容器化部署
Docker Compose编排方案:
yaml复制version: '3'
services:
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:alpine
backend:
build: ./backend
ports: ["8080:8080"]
depends_on: [mysql, redis]
frontend:
build: ./frontend
ports: ["80:80"]
7.2 灰度发布策略
- 按楼栋分批发布前端版本
- 使用Nginx分流控制:
nginx复制# AB测试配置
split_clients "${remote_addr}" $variant {
50% "v2";
* "v1";
}
server {
location / {
proxy_pass http://$variant;
}
}
在校园网环境下特别需要注意:
- 安装包体积控制(主JS文件需<500KB)
- 离线模式支持(使用Service Worker缓存关键资源)
经过三个月的实际运行,系统日均处理订单量达1.2万笔,高峰期QPS稳定在800以上,食堂窗口排队时间平均减少65%。后续计划引入智能推荐算法,基于历史订单实现个性化菜品推荐。
