1. 项目概述
作为一个拥有多年开发经验的程序员,我想分享一个基于SpringBoot+Vue技术的菜谱交流平台的设计与实现过程。这个项目是我最近完成的一个计算机毕业设计,旨在为烹饪爱好者提供一个集菜谱分享、互动交流和管理功能于一体的综合性平台。
在当今快节奏的生活中,越来越多人开始关注健康饮食和烹饪技巧。然而,现有的菜谱平台要么功能单一,要么用户体验不佳。因此,我决定开发这个平台,它采用前后端分离架构,后端使用SpringBoot框架,前端使用Vue.js,数据库采用MySQL,通过MyBatis实现数据持久化。
这个平台的主要特点包括:
- 丰富的菜谱浏览和搜索功能
- 用户互动功能(点赞、收藏、评论)
- 实用的食材计算和营养分析工具
- 完善的社区论坛和资讯系统
- 强大的后台管理功能
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与架构设计
2.1 技术栈选择
在项目初期,我经过仔细的技术调研和对比,最终确定了以下技术栈:
后端技术栈:
- SpringBoot 2.7.0:简化Spring应用的初始搭建和开发过程
- Spring Security:提供认证和授权功能
- MyBatis-Plus:简化数据库操作
- MySQL 8.0:关系型数据库
- Redis:缓存热点数据,提高系统响应速度
前端技术栈:
- Vue.js 3.0:渐进式JavaScript框架
- Element Plus:UI组件库
- Axios:HTTP客户端
- Vue Router:路由管理
- Vuex:状态管理
开发工具:
- IntelliJ IDEA:Java开发IDE
- VS Code:前端开发IDE
- Navicat:数据库管理工具
- Postman:API测试工具
2.2 系统架构设计
系统采用经典的三层架构设计:
- 表现层(UI):负责用户界面展示和交互,使用Vue.js实现
- 业务逻辑层(BLL):处理业务逻辑,使用SpringBoot实现
- 数据层(DL):负责数据存储和访问,使用MySQL+MyBatis实现
架构图如下:
code复制┌───────────────────────────────────────────────────────────────┐
│ 表现层 (Vue.js) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ 组件库 │ │ 路由管理 │ │ 状态管理 │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
└───────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ 业务逻辑层 (SpringBoot) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ 控制器层 │ │ 服务层 │ │ 安全认证 │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
└───────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ 数据层 (MySQL) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ 数据访问层 │ │ 缓存层 │ │ 数据模型 │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
└───────────────────────────────────────────────────────────────┘
2.3 数据库设计
数据库设计采用了规范化的设计方法,主要包含以下核心表:
-
用户相关表:
- user:用户基本信息
- user_group:用户组信息
- auth:权限管理
-
内容相关表:
- recipe_information:菜谱信息
- recipe_type:菜谱分类
- cooking_videos:烹饪视频
- ranking_information:排行信息
-
互动相关表:
- comment:评论
- collect:收藏
- praise:点赞
- forum:论坛
-
工具相关表:
- ingredient_calculator:食材计算器
- nutritional_analysis:营养分析
完整的ER图展示了这些表之间的关系,确保数据的一致性和完整性。
3. 核心功能实现
3.1 用户模块实现
用户模块是系统的基础,包括注册、登录、个人信息管理等功能。
注册功能实现:
java复制@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
public Result register(@RequestBody UserRegisterDTO userDTO) {
// 验证用户名是否已存在
if (userService.existsUsername(userDTO.getUsername())) {
return Result.error("用户名已存在");
}
// 验证邮箱是否已注册
if (userService.existsEmail(userDTO.getEmail())) {
return Result.error("邮箱已注册");
}
// 密码加密
String encodedPassword = passwordEncoder.encode(userDTO.getPassword());
// 创建用户实体
User user = new User();
user.setUsername(userDTO.getUsername());
user.setPassword(encodedPassword);
user.setEmail(userDTO.getEmail());
user.setNickname(userDTO.getNickname());
user.setAvatar(DEFAULT_AVATAR);
// 保存用户
if (userService.save(user)) {
return Result.success("注册成功");
} else {
return Result.error("注册失败");
}
}
}
登录功能实现:
java复制@PostMapping("/login")
public Result login(@RequestBody UserLoginDTO userDTO) {
// 验证用户名和密码
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(userDTO.getUsername(), userDTO.getPassword());
try {
Authentication authentication = authenticationManager.authenticate(authenticationToken);
// 生成JWT令牌
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String token = jwtUtil.generateToken(userDetails);
// 返回令牌和用户基本信息
Map<String, Object> data = new HashMap<>();
data.put("token", token);
data.put("user", userService.getUserInfo(userDetails.getUsername()));
return Result.success("登录成功", data);
} catch (BadCredentialsException e) {
return Result.error("用户名或密码错误");
}
}
3.2 菜谱模块实现
菜谱模块是系统的核心功能,包括菜谱的发布、浏览、搜索等功能。
菜谱发布功能:
java复制@PostMapping("/recipe")
@PreAuthorize("hasRole('USER')")
public Result publishRecipe(@RequestBody RecipePublishDTO recipeDTO) {
// 获取当前用户
User currentUser = getCurrentUser();
// 创建菜谱实体
RecipeInformation recipe = new RecipeInformation();
recipe.setRecipeName(recipeDTO.getRecipeName());
recipe.setRecipeType(recipeDTO.getRecipeType());
recipe.setRe
