1. 项目概述与核心价值
这个基于Spring Boot+Vue的网上订餐系统是我在指导毕业设计时最常推荐的项目之一。它不仅涵盖了企业级应用开发的完整技术栈,更重要的是模拟了真实的外卖平台业务场景。从技术层面看,前后端分离的架构设计、RESTful API的规范实现、权限控制的精细化管理,都是当前Java开发岗位的核心技能要求。
系统采用经典的三层架构:前端Vue.js实现响应式用户界面,后端Spring Boot提供REST API服务,MySQL作为数据存储。这种组合既保证了开发效率,又能满足高并发的业务需求。在实际教学中发现,完整实现这个系统的同学,对Spring Security权限控制、Vue组件化开发、Axios异步通信等关键技术的理解会明显加深。
2. 技术选型与架构设计
2.1 后端技术栈解析
Spring Boot 2.7.x作为基础框架是经过深思熟虑的选择。相比传统SSM框架,它的自动配置特性可以节省大量XML配置时间。我特别推荐使用这些核心依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
数据库设计方面,建议采用这6个核心表:
user(用户表)dish(菜品表)dish_category(菜品分类表)order(订单主表)order_detail(订单明细表)delivery(配送表)
特别注意:订单表一定要做分库分表设计预案,即使毕业设计用不到,这也是面试常考点
2.2 前端架构方案
Vue 3 + Element Plus的组合是经过多个项目验证的稳定方案。脚手架建议使用Vite而非Webpack,构建速度能提升60%以上。这是我的推荐配置:
bash复制npm create vite@latest food-ordering-system --template vue
cd food-ordering-system
npm install element-plus axios vue-router pinia --save
前端工程化方面,必须建立清晰的目录结构:
code复制/src
/api - 所有接口请求
/assets - 静态资源
/components - 公共组件
/router - 路由配置
/store - Pinia状态管理
/utils - 工具函数
/views - 页面组件
3. 核心功能实现细节
3.1 权限控制系统
采用RBAC(基于角色的访问控制)模型,通过Spring Security + JWT实现。这是我优化过的权限验证流程:
- 用户登录成功后生成JWT token
- 前端将token存入localStorage和Vuex/Pinia
- 每次请求通过axios拦截器携带token
- 后端通过OncePerRequestFilter校验token
- 通过@PreAuthorize注解进行方法级权限控制
关键代码片段:
java复制// JWT生成工具类
public class JwtUtil {
private static final String SECRET_KEY = "your-256-bit-secret";
private static final long EXPIRATION = 86400000; // 24小时
public static String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
}
3.2 订单业务处理
订单模块最易出错的是事务处理。建议采用这种设计模式:
java复制@Transactional
public OrderDTO createOrder(OrderDTO orderDTO) {
// 1. 查询菜品(检查库存)
List<OrderDetail> orderDetails = orderDTO.getOrderDetails();
for (OrderDetail detail : orderDetails) {
Dish dish = dishMapper.selectById(detail.getDishId());
if (dish.getStock() < detail.getNumber()) {
throw new BusinessException(ErrorCode.STOCK_NOT_ENOUGH);
}
}
// 2. 扣减库存(乐观锁)
for (OrderDetail detail : orderDetails) {
int update = dishMapper.updateStock(detail.getDishId(), detail.getNumber());
if (update == 0) {
throw new BusinessException(ErrorCode.STOCK_CHANGED);
}
}
// 3. 生成订单(主表+明细)
Order order = new Order();
BeanUtils.copyProperties(orderDTO, order);
orderMapper.insert(order);
orderDetails.forEach(detail -> {
detail.setOrderId(order.getId());
orderDetailMapper.insert(detail);
});
// 4. 清除购物车
cartService.clearCart(orderDTO.getUserId());
return orderDTO;
}
4. 典型问题与解决方案
4.1 跨域问题处理
虽然简单,但90%的同学都会遇到。推荐这种配置方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
4.2 文件上传难题
菜品图片上传建议使用阿里云OSS而非本地存储。关键配置:
yaml复制aliyun:
oss:
endpoint: oss-cn-beijing.aliyuncs.com
access-key-id: your-access-key
access-key-secret: your-secret-key
bucket-name: your-bucket
工具类示例:
java复制public class OssUtil {
public static String upload(MultipartFile file) {
try {
String fileName = UUID.randomUUID() + file.getOriginalFilename();
OSS ossClient = new OSSClientBuilder().build(
endpoint, accessKeyId, accessKeySecret);
ossClient.putObject(bucketName, fileName, file.getInputStream());
ossClient.shutdown();
return "https://" + bucketName + "." + endpoint + "/" + fileName;
} catch (Exception e) {
throw new RuntimeException("文件上传失败");
}
}
}
5. 项目优化建议
5.1 性能优化方案
- 缓存策略:对热门菜品使用Redis缓存
java复制@Cacheable(value = "dish", key = "#id")
public Dish getById(Long id) {
return dishMapper.selectById(id);
}
-
数据库索引优化:为order表的user_id、create_time字段添加联合索引
-
前端懒加载:Vue路由使用动态导入
javascript复制const UserCenter = () => import('../views/UserCenter.vue')
5.2 扩展功能思路
- 支付对接:集成支付宝沙箱环境
- 数据统计:ECharts实现销售数据可视化
- 消息通知:WebSocket实现订单状态实时推送
- 搜索引擎:Elasticsearch实现菜品搜索
6. 开发心得与避坑指南
- 日期处理:前后端统一使用UTC时间戳传输,避免时区问题
- 金额计算:使用BigDecimal而非Double,防止精度丢失
- 密码存储:必须BCrypt加密,绝对禁止明文存储
- API设计:遵循RESTful规范,合理使用HTTP状态码
- 异常处理:全局异常处理器统一返回错误格式
调试技巧:Spring Boot应用启动时添加这个参数,可以看到完整的自动配置报告:
bash复制--debug
在IDEA中运行测试时,我习惯用这个组合键快速重启应用:
code复制Ctrl + F5 (Windows/Linux)
Command + Shift + F5 (Mac)
这个项目最值得深入挖掘的是分布式事务的处理。虽然单机版用@Transactional就够了,但真实场景要考虑:
- 订单服务和库存服务如何保持一致性
- 如何实现最终一致性(Saga模式)
- 幂等性设计防止重复下单
我在实际开发中发现,菜品图片上传功能经常成为性能瓶颈。经过测试对比,采用这些优化后吞吐量提升了3倍:
- 使用WebP格式替代JPEG(体积减少30%)
- 前端实现图片压缩(使用compressorjs库)
- OSS服务端开启图片处理(缩放、水印等)