每年到了毕业设计季节,后台总有一堆同学在问同一个问题:想做点有区分度的题目,但选来选去都是“XX管理系统”“XX平台设计与实现”,答辩时老师看一眼标题就失去了兴趣。
这篇文章就围绕一个具体又比较有代表性的毕业设计题目展开:基于 SpringBoot + 微信小程序 + AI 的智能外卖点餐推荐系统。
先说判断:这个项目真正的竞争点不在“外卖点餐”三个字,而在“智能推荐”这四个字。传统的外卖点餐系统,技术栈再完整,也只是一个 CRUD 展示;但当你把 AI 大模型接入到推荐环节,让系统可以根据用户的历史行为、口味偏好,甚至一段自然语言描述来推荐菜品时,项目的技术含量和答辩说服力就完全不同了。
接下来我会从选题分析、系统架构、数据库设计、SpringBoot 后端实现、微信小程序端实现、推荐引擎与大模型接入、运行验证、常见问题到工程建议,把这个项目完整拆解一遍。就算你还没开始动手写代码,看完这篇也能知道每一步该做什么、为什么这么做。
1. 这篇文章真正要解决的问题
很多计算机专业学生做毕业设计时,会陷入两个极端。
第一个极端是“为了求稳,做一个纯管理系统”。用户管理、菜品管理、订单管理、公告管理,再加几个图表统计,完事。这类系统代码量大,但技术含量低,答辩时老师的提问基本集中在“你的创新点是什么”,而这个问题往往答不上来。
第二个极端是“盲目追新,把项目做得过于复杂”。一上来就要做分布式、微服务、高并发、消息队列,结果工作量失控,写到一半写不下去,反而连基本功能都完不成。
这两个极端之间,真正合适的方向是:用主流可靠的技术栈,完成一个有明确价值主张的业务系统,并在一两个关键环节做出有深度的亮点。
本文要拆解的智能外卖点餐推荐系统,就是一个典型代表。它的技术栈是 SpringBoot + 微信小程序 + MyBatis-Plus + AI 大模型,业务范围是外卖点餐的完整闭环。它的差异化亮点是推荐模块:不是简单地按销量排序,而是结合用户行为数据和 AI 大模型能力,给出有解释、有温度、可交互的推荐结果。
这个题目的价值在于:
- 技术覆盖面广:前后端分离、移动端小程序、数据库设计、接口开发、AI 能力接入,一个项目把本科阶段的核心技能点都串起来了。
- 工作量可控:核心模块清晰,可以按阶段推进,不会出现做到一半失控的情况。
- 答辩有亮点:AI 推荐引擎是老师最容易感兴趣也最容易提问的部分,只要原理讲清楚、效果能演示,这就是论文和答辩的核心加分项。
- 有真实业务场景支撑:外卖点餐是所有人都熟悉的场景,系统边界容易理解,需求分析不会空洞。
如果你正在犹豫毕业设计选题,或者已经选了类似题目但不知道从哪下手,这篇文章值得收藏细读。
2. 智能外卖点餐推荐系统的核心概念
在写代码之前,先弄清楚三组关键概念:推荐系统怎么工作、大模型在推荐里扮演什么角色、它们和外卖点餐场景怎么结合。
2.1 推荐系统的基本逻辑
推荐系统的本质,是在“信息过载”的环境里,帮助用户从大量选择中找到最可能感兴趣的内容。
外卖平台上有几十上百个菜品,用户不可能一一浏览。推荐系统要做的,就是猜:这个用户现在最想吃什么。
常见的推荐算法有三类:
| 推荐类型 | 核心逻辑 | 比喻 | 适合场景 |
|---|---|---|---|
| 基于协同过滤 | “和你口味相似的人也在吃这些” | 朋友推荐 | 有大量用户行为数据 |
| 基于内容推荐 | “你过去爱吃辣,所以推荐辣味菜品” | 口味画像 | 用户历史行为明确 |
| 混合推荐 | 多种策略加权组合,取长补短 | 综合顾问 | 实际系统的主流方案 |
在外卖场景下,协同过滤有一个现实难题:如果用户是新用户,或者订单数据很少,协同过滤就无从算起。这就是所谓“冷启动问题”。
解决冷启动,传统方案是“热门兜底”,也就是推荐销量最高、评分最好的菜品。而在这个项目里,我们可以用 AI 大模型做更高级的冷启动处理:让用户用一句话描述今天想吃什么,系统基于自然语言理解来推荐。这是传统推荐系统做不到的。
2.2 大模型在推荐系统中的角色
大模型不是来替代整个推荐系统的,而是作为其中一个关键组件,负责两件事:
第一,理解用户的自然语言输入。传统系统里,用户只能点按钮、选分类、看列表;接入了大模型之后,用户可以输入“今天想吃点清淡的,不要太辣,适合一个人吃”,系统解析出关键词:口味清淡、不吃辣、一人食,然后到菜品库中匹配候选集。
第二,生成推荐解释。推荐系统算出结果之后,如果只是丢给用户一个菜品列表,说服力有限。大模型可以为每个推荐结果生成一句推荐语,比如“这道番茄鸡蛋汤口味清淡,酸甜开胃,一个人吃刚刚好,适合今天没什么胃口的你”。这大大提升了用户体验,也能在答辩时作为“AI 能力落地”的直接证据。
2.3 系统里有哪些角色
一个完整的外卖点餐推荐系统,至少要包含三种角色:
- 普通用户:浏览菜品、搜索、下单、查看订单、查看个性化推荐。
- 管理员:管理菜品分类、菜品信息、用户状态、订单状态、推荐策略配置。
- 系统(后台服务):处理业务逻辑,调用推荐引擎和大模型接口。
这三类需求叠加起来,系统的功能边界就清楚了。
3. 系统架构与技术选型
这个项目的架构,属于典型的小型前后端分离架构。它不追求微服务级别的拆分,但要求层次清晰、职责分明。
整体架构分为三层:
第一层是微信小程序端,承担用户交互。用户在小程序里浏览菜品、查看推荐、下单支付、管理个人信息。小程序通过 HTTP 请求调用后端接口,数据交换格式为 JSON。
第二层是SpringBoot 后端服务,承担业务逻辑。后端分成控制层、服务层、数据访问层。控制层负责接收请求和返回结果;服务层实现具体业务,比如下单流程、推荐流程;数据访问层使用 MyBatis-Plus 操作数据库。
第三层是数据与外部能力层,包括 MySQL 数据库存储业务数据,以及 AI 大模型接口能力。大模型接口在这一层以 HTTP 的方式被后端服务调用,后端不直接面向小程序暴露大模型的密钥和配置。
这种分层的好处是,每一层都可以独立修改和替换。比如今天接的是某一个云端大模型接口,明天想换成本地部署的模型,只需要修改后端调用大模型的 Service 实现,小程序端完全不用动。
核心模块划分如下:
| 模块 | 主要功能 | 涉及技术 |
|---|---|---|
| 用户模块 | 微信登录、用户信息维护 | SpringBoot、MyBatis-Plus |
| 菜品模块 | 分类浏览、菜品详情 | SpringBoot、MySQL |
| 订单模块 | 购物车、下单、订单查询 | SpringBoot、MyBatis-Plus |
| 推荐模块 | 相似菜品推荐、大模型个性化推荐 | 推荐算法、AI 大模型接口 |
| 管理模块 | 菜品管理、订单管理、推荐管理 | SpringBoot、Vue 或原生页面 |
这里要特别提醒一点:不要在一开始就追求复杂架构。把 SpringBoot 工程拆成 controller / service / mapper 三个标准包,再加上一个 config 包和一个 common 包,对毕业设计来说完全足够,也方便论文画架构图。
4. 环境准备与数据库设计
4.1 开发环境清单
在动手之前,先把环境准备好。以下环境以实际安装版本为准,本文侧重通用实现思路,不在版本号上死磕。
- JDK 1.8 或 17,推荐使用稳定版本。
- Maven 3.6 以上,用于依赖管理。
- MySQL 5.7 或 8.0,存储业务数据。
- 微信开发者工具,用于运行小程序端。
- IDEA 或 Eclipse,用于后端开发。
- 一个可用的 AI 大模型接口,本文以兼容 OpenAI 格式的 API 为例,也可以用国内大模型平台的接口,只需替换 SDK 和 base-url。
4.2 数据库设计
数据库是业务系统的地基。这个项目建议设计如下核心表:
用户表 t_user
CREATE TABLE `t_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `openid` varchar(64) DEFAULT NULL COMMENT '微信openid', `nickname` varchar(50) DEFAULT NULL COMMENT '昵称', `avatar` varchar(255) DEFAULT NULL COMMENT '头像', `phone` varchar(20) DEFAULT NULL COMMENT '手机号', `taste_tag` varchar(255) DEFAULT NULL COMMENT '口味偏好标签,如辣、清淡', `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';菜品表 t_dish
CREATE TABLE `t_dish` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `category_id` bigint(20) DEFAULT NULL COMMENT '分类id', `name` varchar(100) DEFAULT NULL COMMENT '菜品名称', `description` varchar(500) DEFAULT NULL COMMENT '菜品描述', `price` decimal(10,2) DEFAULT NULL COMMENT '价格', `image` varchar(255) DEFAULT NULL COMMENT '图片地址', `spicy_level` int(11) DEFAULT 0 COMMENT '辣度,0不辣 1微辣 2中辣 3特辣', `taste_tags` varchar(255) DEFAULT NULL COMMENT '口味标签,如清淡、重口、甜口', `sales_count` int(11) DEFAULT 0 COMMENT '销量', `status` int(11) DEFAULT 1 COMMENT '上架状态 1上架 0下架', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜品表';用户行为表 t_user_behavior
CREATE TABLE `t_user_behavior` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) DEFAULT NULL COMMENT '用户id', `dish_id` bigint(20) DEFAULT NULL COMMENT '菜品id', `behavior_type` varchar(20) DEFAULT NULL COMMENT '行为类型:view点赞、order下单、collect收藏', `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户行为记录表';订单表 t_order和订单明细表 t_order_item也必不可少,订单表记录订单号、用户、总金额、状态;订单明细表记录每个订单包含哪些菜品、数量、单价。
这里的设计思路是:推荐系统的基础数据来自用户的真实行为。用户浏览了哪些菜、收藏了哪些菜、下单了哪些菜,这些行为是判断用户口味偏好的原始依据。如果项目演示阶段缺少真实数据,可以写一个数据初始化脚本,批量生成模拟用户行为数据。
5. SpringBoot 后端核心实现
SpringBoot 是整个系统的中枢。下面按依赖、配置、代码三层来拆解。
5.1 Maven 依赖
在pom.xml中引入核心依赖:SpringBoot Web、MyBatis-Plus、MySQL 驱动、Lombok,以及大模型 HTTP 调用所需的工具包。
<!-- 文件路径:pom.xml --> <dependencies> <!-- SpringBoot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis-Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- Hutool 工具包,封装了 HTTP 请求 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.18</version> </dependency> </dependencies>Hutool 在调用大模型 API 时非常方便,不需要额外引入 Feign 或 RestTemplate 的复杂配置。
5.2 application.yml 配置
# 文件路径:src/main/resources/application.yml server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/ai_order?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password servlet: multipart: max-file-size: 10MB mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 # AI 大模型接口配置 ai: model: api-key: your_api_key_here base-url: https://your-model-endpoint.com/v1 model-name: your-model-name这里最需要强调的是ai.model.api-key。这个配置项绝对不能写死在小程序前端,也不能提交到公开的代码仓库。实际项目里,建议通过环境变量或配置中心注入,比如api-key: ${AI_API_KEY}。
5.3 菜品推荐接口实现
推荐模块是核心亮点,单独拆出来讲。
推荐接口的流程是:
- 用户进入小程序首页,请求
/api/recommend/list。 - 后端拿到用户 ID,查询用户历史行为记录。
- 如果用户行为数据充足,使用基于用户的协同过滤思想,找到相似用户,推荐他们喜欢的菜品。
- 如果用户行为数据不足,使用用户输入的偏好文本,调用大模型解析口味关键词,然后按标签匹配菜品。
- 最终结果统一包装成
RecommendResponse返回给小程序。
先定义一个菜品实体:
// 文件路径:src/main/java/com/example/aiorder/entity/Dish.java @Data @TableName("t_dish") public class Dish { @TableId(type = IdType.AUTO) private Long id; private Long categoryId; private String name; private String description; private BigDecimal price; private String image; private Integer spicyLevel; private String tasteTags; private Integer salesCount; private Integer status; }再写推荐服务的核心逻辑:
// 文件路径:src/main/java/com/example/aiorder/service/RecommendService.java @Service public class RecommendService { @Resource private DishMapper dishMapper; @Resource private UserBehaviorMapper behaviorMapper; @Resource private AiModelService aiModelService; public List<Dish> recommend(Long userId, String userInput) { // 1. 查询用户历史行为,统计兴趣标签 List<UserBehavior> behaviors = behaviorMapper.selectList( new LambdaQueryWrapper<UserBehavior>() .eq(UserBehavior::getUserId, userId) .orderByDesc(UserBehavior::getCreateTime) .last("limit 50") ); // 2. 根据行为记录,计算用户口味标签权重 Map<String, Integer> tagWeight = new HashMap<>(); if (behaviors.isEmpty() && StrUtil.isNotBlank(userInput)) { // 3. 冷启动:调用大模型解析用户输入,提取标签 List<String> tags = aiModelService.analyzeUserInput(userInput); return matchDishByTags(tags); } // 4. 有行为数据:基于标签权重推荐 for (UserBehavior behavior : behaviors) { Dish dish = dishMapper.selectById(behavior.getDishId()); if (dish != null && StrUtil.isNotBlank(dish.getTasteTags())) { for (String tag : dish.getTasteTags().split(",")) { tagWeight.put(tag, tagWeight.getOrDefault(tag, 0) + 1); } } } // 5. 按权重排序,取 Top 标签,再匹配菜品 List<String> topTags = tagWeight.entrySet().stream() .sorted(Map.Entry.<String, Integer>comparingByValue().reversed()) .limit(3) .map(Map.Entry::getKey) .collect(Collectors.toList()); return matchDishByTags(topTags); } private List<Dish> matchDishByTags(List<String> tags) { // 按标签模糊匹配菜品,并按销量排序 return dishMapper.selectList( new LambdaQueryWrapper<Dish>() .eq(Dish::getStatus, 1) .like(StrUtil.isNotBlank(tags.get(0)), Dish::getTasteTags, tags.get(0)) .orderByDesc(Dish::getSalesCount) .last("limit 10") ); } }控制层接口:
// 文件路径:src/main/java/com/example/aiorder/controller/RecommendController.java @RestController @RequestMapping("/api/recommend") public class RecommendController { @Resource private RecommendService recommendService; @GetMapping("/list") public Result<List<Dish>> recommend( @RequestParam(required = false) Long userId, @RequestParam(required = false) String userInput) { List<Dish> dishes = recommendService.recommend(userId, userInput); return Result.success(dishes); } }这个实现有几个关键点值得注意。
第一,LambdaQueryWrapper是 MyBatis-Plus 提供的条件构造器,用起来比手写 XML 高效很多,也是毕业设计代码里的加分细节。
第二,冷启动处理是推荐系统的核心难点。这里用了“用户没有行为数据时,通过自然语言输入 + 大模型标签提取”的方案,比单纯返回热门菜品更有技术说服力。
第三,推荐过程不是一次性把大模型接口放到主链路里,而是先标签化、再匹配、再排序,这样可以保证接口响应速度。直接让大模型生成整个推荐列表,响应慢且结果不可控,这是实际系统里的常见坑。
6. 大模型接入与提示词工程
大模型在这个项目里,除了做冷启动标签解析,还可以做推荐解释生成。这部分是答辩时的展示亮点。
6.1 大模型调用服务
// 文件路径:src/main/java/com/example/aiorder/service/AiModelService.java @Service public class AiModelService { @Value("${ai.model.api-key}") private String apiKey; @Value("${ai.model.base-url}") private String baseUrl; @Value("${ai.model.model-name}") private String modelName; public List<String> analyzeUserInput(String userInput) { String prompt = buildPrompt(userInput); String response = callModel(prompt); return parseTags(response); } public String generateRecommendReason(String dishName, String userInput) { String prompt = "请用一句话为菜品【" + dishName + "】生成推荐理由," + "用户的需求是:" + userInput + "。要求语言自然、贴合场景,不超过30个字。"; return callModel(prompt); } private String callModel(String prompt) { Map<String, Object> params = new HashMap<>(); params.put("model", modelName); params.put("messages", new Object[]{ Map.of("role", "user", "content", prompt) }); params.put("temperature", 0.7); String body = JSONUtil.toJsonStr(params); HttpResponse response = HttpRequest.post(baseUrl + "/chat/completions") .header("Authorization", "Bearer " + apiKey) .header("Content-Type", "application/json") .body(body) .timeout(10000) .execute(); return response.body(); } }6.2 提示词模板
提示词直接决定了大模型输出质量。同一个需求,提示词写得好不好,效果差异巨大。
弱提示词:
请根据用户的输入推荐菜品。强提示词:
你是一个专业的美食推荐助手。请从用户的描述中提取口味标签,标签范围包括:辣、清淡、甜口、酸口、重口、素食、低脂、一人食、多人聚餐。 用户描述:${userInput} 请只输出标签列表,用逗号分隔,不要输出其他内容。强提示词的要点是:定义角色、明确任务、限定输出格式。这样大模型就不会输出一大堆解释,而是乖乖返回“清淡,一人食,不辣”这样的结构化标签。
提示词要单独写成一个常量类,方便调优和论文里展示。
6.3 大模型与推荐链路的关系
要清楚一点:大模型不是推荐的主体,而是推荐链路上的辅助组件。推荐的主体还是基于用户行为和标签匹配的算法逻辑。大模型负责两件事:解析语义标签、生成推荐语。
这样设计有实际好处。第一,响应速度快。菜品匹配和排序走数据库索引,毫秒级返回;大模型只用在小概率的冷启动和解释生成场景。第二,结果稳定。数据库标签匹配的结果是可复现的,不会出现同一个用户两次请求推荐结果完全不一样的情况。第三,成本可控。大模型按调用次数计费,如果每次请求都调用大模型,成本高且答辩演示时万一网络不通,整个推荐模块就瘫痪了。
7. 微信小程序端实现
小程序端是用户直接接触的界面,好坏直接影响演示效果。小程序包括四个核心页面:首页、点餐页、购物车与订单页、个人中心页。
7.1 首页推荐展示
首页进入时,调用推荐接口,渲染推荐菜品列表。用户可以在顶部搜索框输入口味偏好,比如“今天想吃点辣的开开胃”,然后触发推荐。
// 文件路径:pages/index/index.js Page({ data: { recommendList: [], userInput: '' }, onLoad() { this.fetchRecommend(''); }, fetchRecommend(input) { const app = getApp(); wx.request({ url: app.globalData.baseUrl + '/api/recommend/list', method: 'GET', data: { userId: app.globalData.userId, userInput: input }, success: (res) => { if (res.data.code === 200) { this.setData({ recommendList: res.data.data }); } } }); }, onInputChange(e) { this.setData({ userInput: e.detail.value }); }, onSearch() { this.fetchRecommend(this.data.userInput); } });对应的小程序页面结构:
<!-- 文件路径:pages/index/index.wxml --> <view class="search-bar"> <input placeholder="输入你的口味偏好,例如:想吃清淡的" bindinput="onInputChange" /> <button bindtap="onSearch">智能推荐</button> </view> <view class="recommend-list"> <view class="dish-card" wx:for="{{recommendList}}" wx:key="id"> <image src="{{item.image}}" /> <view class="dish-info"> <text class="dish-name">{{item.name}}</text> <text class="dish-desc">{{item.description}}</text> <text class="dish-price">¥{{item.price}}</text> <button bindtap="addToCart">// 文件路径:pages/cart/cart.js submitOrder() { const cartList = this.data.cartList; const app = getApp(); wx.request({ url: app.globalData.baseUrl + '/api/order/create', method: 'POST', data: { userId: app.globalData.userId, items: cartList.map(item => ({ dishId: item.id, quantity: item.quantity })) }, success: (res) => { if (res.data.code === 200) { wx.showToast({ title: '下单成功' }); this.setData({ cartList: [] }); } } }); }后端订单创建的代码这里先不做完整展开,核心逻辑是:事务开启后,先写入订单主表,再循环写入订单明细表,同时扣减菜品销量字段,最后提交事务。涉及金额和库存的操作,事务是必须的。
需要提醒的是,如果项目涉及微信支付,需要小程序具备微信支付商户号资质。如果是毕业设计演示,一般建议把支付模块做成模拟支付,也就是在界面上提供一个“模拟支付”按钮,跳到支付成功页。这样既不影响完整流程演示,也不会卡在资质审核上。
8. 运行效果与验证方法
项目写完以后,验证环节不能省。按下面顺序操作,能较快发现问题。
8.1 后端启动
mvn clean package -DskipTests java -jar target/ai-order-0.0.1-SNAPSHOT.jar看到类似输出说明启动成功:
Tomcat started on port(s): 8080 (http) Started AiOrderApplication in 5.23 seconds8.2 接口验证
启动后端后,用浏览器直接访问推荐接口:
http://localhost:8080/api/recommend/list?userId=1&userInput=想吃清淡的预期返回 JSON 格式的菜品列表。如果返回了菜品数据,说明数据库连接、MyBatis-Plus 映射、推荐逻辑都正常。
8.3 小程序端验证
在微信开发者工具中导入小程序项目,修改app.js里的baseUrl,指向本机局域网 IP 或已部署的服务器地址。
验证时重点检查几个场景:
- 新用户首次进入,不输入任何内容,能看到“热门推荐”兜底菜品。
- 新用户输入“想吃点辣的”,推荐结果与辣味菜品匹配。
- 老用户多次浏览和收藏某类菜品后,推荐结果中同类菜品占比上升。
- 用户可以将菜品加入购物车、提交订单、在订单列表看到订单记录。
- 管理员后台可以新增菜品,客户端刷新后能看到新菜品。
如果第 2 项和第 3 项表现不明显,最可能的原因是菜品数据里没有维护taste_tags字段,或者行为数据太少。解决方法是先造一批带有明确标签的菜品数据,再生成足够的模拟行为数据。
9. 常见问题与排查思路
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 后端启动报数据库连接失败 | MySQL 未启动或账号密码错误 | 查看日志中最后一条异常堆栈 | 检查数据库服务和application.yml配置 |
| 小程序请求接口报 500 | 后端接口异常 | 打开浏览器直接访问接口,查看后端控制台日志 | 根据异常堆栈修复代码,常见是 SQL 错误或空指针 |
| 小程序请求接口报 404 | 请求路径与后端接口不一致 | 对比控制层@RequestMapping和小程序 URL | 统一接口路径,建议用常量管理 |
| 推荐结果为空 | 数据库中无匹配标签的菜品 | 查看t_dish表taste_tags字段 | 为菜品补充口味标签数据 |
| AI 接口调用超时 | 网络不稳定或模型响应慢 | 查看后端日志是否有超时异常 | 调整超时时间,增加备用模型接口 |
| 大模型返回内容无法解析 | 提示词输出格式不稳定 | 打印大模型原始返回内容 | 优化提示词,限定 JSON 或纯标签输出格式 |
| 小程序页面白屏 | JS 报错或路径错误 | 打开开发者工具调试器 Console 面板 | 根据报错修复页面逻辑 |
| 启动时依赖冲突 | spring-boot 与 mybatis-plus 版本不匹配 | 执行mvn dependency:tree查看依赖树 | 统一 SpringBoot 与 MyBatis-Plus 版本 |
10. 最佳实践与工程建议
毕业设计不只是把功能跑通,更要在论文和答辩中体现工程思维。下面这些建议,是项目真正拉开差距的地方。
10.1 代码规范
包名统一使用com.example.aiorder,尽量用有意义的类名。实体类用@Data注解避免手写 Getter/Setter。Controller 只负责参数接收和结果返回,不要写业务逻辑。Service 中处理业务,Mapper 只操作数据。
10.2 安全性
第一,大模型 API Key 必须放在后端配置里,由环境变量注入,不能出现在小程序代码或前端请求里。第二,小程序端的登录要使用微信授权 code,后端通过 code 换取 openid,再建立自己的用户体系,而不是直接拿前端传的用户 ID 做所有操作。第三,管理端接口要增加管理员鉴权,避免任意用户直接调用管理接口。
10.3 推荐效果优化
如果想让推荐结果更合理,可以在行为标签计算中加入时间衰减。比如,30 天前的行为权重为 0.5,一周内的行为权重为 1.0。这样即使用户以前爱吃辣、最近口味变清淡,推荐结果也能跟上变化。
10.4 答辩准备
这个题目答辩时,老师大概率会问三个问题:
第一个问题:推荐算法用了什么? 回答思路:基于标签的推荐,结合用户行为数据统计口味偏好,配合大模型冷启动解析。协同过滤是理论基础,实际实现时简化成标签匹配,保证响应速度。
第二个问题:大模型在系统里起什么作用? 回答思路:不承担全部推荐,只负责两个环节——冷启动时解析自然语言、生成推荐解释。主链路还是传统算法,这样可以解释为什么系统稳定、可控、成本低。
第三个问题:推荐效果怎么评价? 回答思路:可以用点击率或下单转化率来验证。项目里设计一张用户行为表,如果用户看了推荐菜品之后产生了下单行为,说明推荐有效。可以统计推荐位的下单转化率作为效果指标。
10.5 版本管理
开发过程中建议从第一天就用 Git 管理代码。后端、小程序、数据库脚本、论文文档分类存放在不同目录。即使只有一个人开发,版本管理也能让你随时回退到可运行的状态,避免改崩了无法恢复的尴尬局面。
11. 总结与后续学习方向
这个智能外卖点餐推荐系统,本质上是一次整合实践。SpringBoot 处理业务与接口,微信小程序解决用户触达,MySQL 承载数据,AI 大模型为推荐体验注入智能化能力。四者组合在一起,形成了比普通管理系统更有技术深度的毕业设计选题。
文章已经把核心的技术链路拆完了:从需求分析到架构设计,从数据库建模到后端实现,从大模型接入到小程序开发,从运行验证到答辩准备。照着这个思路推进,每一步都清楚。
接下来你可以按三个方向继续深入学习。
第一个方向是推荐系统本身。学一下协同过滤、矩阵分解、向量召回,把这些算法逐步替换掉现在用的标签匹配,这就是从一个毕业设计项目迈向真实工业级推荐系统的一条学习路径。
第二个方向是大模型应用开发。重点研究提示词工程、模型微调和 Agent 编排。当前大模型能力更新非常快,用同一个系统接入 ChatGPT、文心一言、通义千问、DeepSeek 等模型,只需要改配置和少量代码,这个敏感性非常有价值。
第三个方向是工程化能力。把项目部署到云服务器,配置 HTTPS 域名,接入微信支付,完善日志和监控体系。如果这套都完成了,你掌握的就已经超过“毕业设计”的层面了。
如果有条件,强烈建议把项目跑起来,认真走一遍完整流程。遇到问题不要急,回头查看第 9 节的排查表和系统日志,大多数问题都能快速定位。祝项目顺利完成,答辩顺利。