1. 项目背景与核心价值
成都作为联合国教科文组织认证的"美食之都",其餐饮文化具有鲜明的地域特色和深厚的群众基础。2022年成都市餐饮收入突破1100亿元,同比增长8.7%,显示出强劲的市场需求。但传统美食推荐存在信息分散、更新滞后等问题,这正是我们开发"成都美食分享系统"的现实背景。
这个基于SpringBoot+小程序的毕业设计项目,实现了从后台管理到前端展示的全栈解决方案。其核心价值体现在三个维度:
- 对开发者:完整展示了企业级应用的技术架构,包含用户认证、数据管理、接口设计等实战要素
- 对餐饮从业者:提供了精准的线上曝光渠道,支持图文、评分等多维展示
- 对游客/本地居民:解决了"吃什么"的决策难题,通过LBS推荐实现个性化美食发现
提示:系统采用前后端分离架构,后台使用SpringBoot 2.7.x稳定版,前端使用微信小程序原生开发,这种组合既保证了后台服务的可靠性,又兼顾了前端用户的易用性。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 后端技术栈设计
SpringBoot作为基础框架,其自动配置特性大幅简化了项目初始化工作。我们通过starter依赖集成了以下核心组件:
- 持久层:MyBatis-Plus 3.5.3 + Druid连接池
- 动态表名处理器实现多租户数据隔离
- 性能监控SQL防火墙配置
- 安全控制:Spring Security OAuth2
- JWT令牌有效期设置为7200秒
- 密码加密采用BCryptPasswordEncoder
- 文件存储:阿里云OSS SDK
- 图片压缩使用Thumbnails组件
- 断点续传功能实现大文件上传
java复制// 示例:美食数据分页查询接口
@GetMapping("/foods")
public R<Page<FoodVO>> listFoods(
@RequestParam(required = false) String keyword,
@RequestParam(defaultValue = "1") Integer pageNo,
@RequestParam(defaultValue = "10") Integer pageSize) {
LambdaQueryWrapper<Food> wrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(keyword)) {
wrapper.like(Food::getName, keyword);
}
Page<Food> page = foodService.page(new Page<>(pageNo, pageSize), wrapper);
return R.success(page.convert(this::convertToVO));
}
2.2 小程序端关键技术
微信小程序端采用MINA框架开发,重点解决了以下技术难点:
- 地图定位:使用wx.getLocation获取坐标,配合腾讯地图SDK实现
- 注意需要在app.json中声明requiredPrivateInfos
- 图片懒加载:通过IntersectionObserver API实现
- 可视区域阈值设置为50px缓冲
- 自定义导航栏:navigationStyle设置为custom后
- 需要动态计算胶囊按钮位置(iOS/Android差异处理)
javascript复制// 获取系统状态栏高度
const getStatusBarHeight = () => {
const { statusBarHeight } = wx.getSystemInfoSync()
return statusBarHeight || 20
}
// 计算导航栏总高度
export const getNavBarHeight = () => {
const menuButton = wx.getMenuButtonBoundingClientRect()
return menuButton.bottom + menuButton.top - getStatusBarHeight()
}
3. 核心功能实现细节
3.1 美食推荐算法
系统采用混合推荐策略,具体实现逻辑如下表所示:
| 推荐类型 | 数据来源 | 算法实现 | 权重 |
|---|---|---|---|
| 基于位置 | 用户GPS坐标 | 球面距离公式计算 | 40% |
| 基于热度 | 浏览/收藏量 | 时间衰减因子处理 | 30% |
| 基于标签 | 用户历史行为 | TF-IDF向量相似度 | 30% |
距离计算公式实现:
java复制public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
double R = 6371; // 地球半径(km)
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
3.2 评论敏感词过滤
采用AC自动机算法实现高效过滤:
- 初始化敏感词库(从文件加载)
- 构建失败指针实现快速跳转
- 实现异步审核机制:
- 先返回前端"审核中"状态
- 后台线程完成最终过滤后更新状态
java复制// AC自动机节点结构
class ACTrieNode {
Map<Character, ACTrieNode> children = new HashMap<>();
ACTrieNode fail;
boolean isEnd;
int length;
}
// 过滤处理核心逻辑
public String filter(String text) {
ACTrieNode node = root;
StringBuilder result = new StringBuilder(text);
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
while (node != null && !node.children.containsKey(c)) {
node = node.fail;
}
if (node == null) {
node = root;
continue;
}
node = node.children.get(c);
if (node.isEnd) {
int start = i - node.length + 1;
result.replace(start, i+1, "***");
}
}
return result.toString();
}
4. 项目部署与优化
4.1 生产环境配置
采用Docker Compose编排服务,关键配置如下:
yaml复制version: '3'
services:
app:
image: openjdk:11-jre
ports:
- "8080:8080"
volumes:
- ./logs:/app/logs
environment:
- SPRING_PROFILES_ACTIVE=prod
- REDIS_HOST=redis
redis:
image: redis:6-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
redis_data:
4.2 性能优化实践
通过JMeter压测发现并解决的典型问题:
-
N+1查询问题:
- 现象:获取美食列表时产生大量店铺查询
- 解决:添加@BatchSize注解优化懒加载
-
缓存穿透防护:
- 现象:随机ID攻击导致DB负载飙升
- 方案:布隆过滤器+空值缓存
-
小程序首屏加载:
- 优化前:2.8s (3G网络)
- 优化措施:
- 图片WebP格式转换
- 接口数据预取
- 分包加载策略
- 优化后:1.2s
5. 毕业设计扩展建议
基于现有系统可深化以下方向:
-
智能推荐升级:
- 接入HanLP实现评论情感分析
- 使用协同过滤算法优化推荐
-
运营功能增强:
- 直播带货模块集成
- 限时秒杀活动系统
-
技术深度探索:
- SpringBoot自动装配原理实践
- 微信支付V3接口对接
- 分布式事务解决方案
注意:数据库设计时建议预留20%的冗余字段,为后续功能扩展做好准备。例如我们最初未考虑短视频功能,后来通过添加video_url字段快速实现了该需求。
我在实际开发中深刻体会到,美食类系统需要特别关注:
- 图片处理性能(建议使用CDN加速)
- 实时评分计算(采用滑动窗口算法)
- 多端一致性(通过WebSocket同步状态)
这个项目从技术选型到最终上线,完整走通了互联网产品开发全流程,对掌握现代Web开发技术栈具有典型参考价值。特别是SpringBoot与小程序这种"重型后台+轻量前端"的组合,非常适合作为全栈开发的入门实践。
