1. 项目概述
这个基于Spring Boot和Vue的私房菜上门服务系统是我在毕业设计期间完成的一个完整项目。作为一名计算机专业的学生,我选择这个题目是因为看到了当前餐饮行业数字化转型的趋势,特别是私房菜这种个性化餐饮服务的市场需求。系统采用前后端分离架构,后端使用Spring Boot框架,前端使用Vue.js,数据库采用MySQL,实现了一个功能完善的私房菜预订和服务平台。
提示:在开发类似餐饮服务平台时,建议优先考虑移动端适配性,因为大部分用户会通过手机访问这类服务。
2. 系统架构设计
2.1 技术选型分析
选择Spring Boot作为后端框架主要基于以下几个考虑:
- 快速开发:Spring Boot的自动配置和起步依赖大大简化了项目搭建过程
- 微服务友好:便于后期扩展为微服务架构
- 丰富的生态系统:Spring生态中有大量成熟的解决方案
- 良好的社区支持:遇到问题容易找到解决方案
前端选择Vue.js是因为:
- 渐进式框架,学习曲线平缓
- 组件化开发,代码复用性高
- 响应式数据绑定,开发效率高
- 活跃的社区和丰富的第三方库
2.2 系统架构图
系统采用典型的三层架构:
- 表现层:Vue前端应用
- 业务逻辑层:Spring Boot后端服务
- 数据访问层:MySQL数据库
code复制┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Vue前端 │ ←→ │ Spring Boot │ ←→ │ MySQL数据库 │
└─────────────┘ └─────────────┘ └─────────────┘
3. 核心功能实现
3.1 用户模块
用户模块分为三类角色:
- 普通用户:可以浏览菜品、下单、参与社区交流
- 厨师用户:可以管理自己的菜品和订单
- 管理员:负责系统整体管理和内容审核
用户注册流程关键代码示例:
java复制@PostMapping("/register")
public ResponseEntity<?> registerUser(@RequestBody UserDTO userDTO) {
// 验证用户名是否已存在
if (userRepository.existsByUsername(userDTO.getUsername())) {
return ResponseEntity.badRequest().body("用户名已存在");
}
// 创建新用户
User user = new User();
user.setUsername(userDTO.getUsername());
user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
user.setRole(userDTO.getRole());
userRepository.save(user);
return ResponseEntity.ok("注册成功");
}
3.2 菜品管理模块
菜品管理是系统的核心功能之一,主要包含:
- 菜品分类管理
- 菜品信息CRUD
- 菜品搜索和筛选
菜品实体类设计:
java复制@Entity
@Table(name = "dishes")
public class Dish {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String category;
private Double price;
private String description;
@Lob
private String ingredients;
@Lob
private String cookingSteps;
@ManyToOne
@JoinColumn(name = "chef_id")
private User chef;
// 省略getter和setter
}
3.3 订单管理模块
订单管理实现了完整的预订流程:
- 用户选择菜品并提交预订
- 厨师确认订单
- 用户支付
- 服务完成后的评价
订单状态机设计:
java复制public enum OrderStatus {
PENDING, // 待确认
CONFIRMED, // 已确认
PAID, // 已支付
COMPLETED, // 已完成
CANCELLED, // 已取消
REFUNDED // 已退款
}
4. 关键技术实现
4.1 前后端分离架构
前端Vue项目通过axios与后端API通信:
javascript复制// api.js
import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:8080/api',
timeout: 5000
});
// 请求拦截器
api.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
export default api;
4.2 权限控制实现
使用Spring Security实现基于角色的权限控制:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/user/**").hasAnyRole("USER", "CHEF", "ADMIN")
.antMatchers("/api/chef/**").hasAnyRole("CHEF", "ADMIN")
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
}
4.3 文件上传处理
菜品图片上传实现:
java复制@PostMapping("/dishes/{id}/image")
public ResponseEntity<?> uploadDishImage(
@PathVariable Long id,
@RequestParam("file") MultipartFile file) {
Dish dish = dishRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("菜品不存在"));
try {
String fileName = fileStorageService.storeFile(file);
dish.setImageUrl(fileName);
dishRepository.save(dish);
return ResponseEntity.ok("图片上传成功");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("图片上传失败");
}
}
5. 系统测试与优化
5.1 功能测试用例
| 测试项 | 测试步骤 | 预期结果 | 实际结果 |
|---|---|---|---|
| 用户注册 | 1. 访问注册页面 2. 填写有效信息提交 |
注册成功,跳转到登录页 | 符合预期 |
| 菜品搜索 | 1. 在搜索框输入关键词 2. 点击搜索按钮 |
显示相关菜品列表 | 符合预期 |
| 订单支付 | 1. 创建订单 2. 模拟支付流程 |
订单状态变更为已支付 | 符合预期 |
5.2 性能优化措施
-
数据库优化:
- 为常用查询字段添加索引
- 合理设计表关系,避免过度连接
-
缓存策略:
- 使用Redis缓存热门菜品数据
- 实现页面静态化减少服务器压力
-
前端优化:
- 图片懒加载
- 组件按需加载
- 减少不必要的API调用
6. 开发经验总结
在开发这个系统的过程中,我遇到了几个关键挑战并找到了解决方案:
- 跨域问题:前后端分离开发时,浏览器会阻止跨域请求。解决方案是在后端添加CORS配置:
java复制@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
- 状态管理:随着应用复杂度增加,前端状态管理变得困难。我采用了Vuex来集中管理应用状态:
javascript复制const store = new Vuex.Store({
state: {
user: null,
cart: []
},
mutations: {
setUser(state, user) {
state.user = user;
},
addToCart(state, item) {
state.cart.push(item);
}
}
});
- 部署问题:将前后端项目部署到生产环境时,需要注意:
- 前端静态文件需要正确配置Nginx
- 后端应用需要配置正确的数据库连接
- 确保文件上传目录有写入权限
这个项目让我对全栈开发有了更深入的理解,特别是在系统架构设计和模块划分方面收获很大。通过实际开发,我也更加熟悉了Spring Boot和Vue的生态系统,以及如何将它们有效地结合起来构建一个完整的Web应用。