1. 项目背景与技术选型
网上点餐系统作为典型的Web应用,完美契合了当前餐饮行业数字化转型的需求。我选择SpringBoot+Vue这套技术栈,主要基于以下几个考量:
首先,SpringBoot的"约定优于配置"理念大幅降低了Java后端开发的复杂度。相比传统的SSM框架,SpringBoot通过自动配置机制减少了80%以上的XML配置工作。例如,只需在pom.xml中添加spring-boot-starter-web依赖,就能自动配置好Tomcat和Spring MVC环境。
其次,Vue.js的渐进式特性非常适合中小型项目的前端开发。与React和Angular相比,Vue的学习曲线更平缓,模板语法更直观。特别是配合Element UI组件库,可以在极短时间内构建出专业的管理界面。
数据库方面,MySQL作为最流行的开源关系型数据库,其5.7版本在事务性能和JSON支持上都有显著提升,完全能满足点餐系统的数据存储需求。考虑到系统可能面临的高并发场景,我在架构设计中预留了Redis缓存层的位置。
2. 系统架构设计
2.1 前后端分离架构
系统采用经典的前后端分离架构,后端提供RESTful API接口,前端通过axios进行消费。这种架构的优势在于:
- 开发解耦:前后端可以并行开发,只需约定好接口文档
- 部署独立:前端可部署在Nginx,后端可打包为独立JAR
- 技术栈灵活:未来可轻松替换前端框架或扩展移动端
2.2 后端分层设计
后端采用标准的三层架构:
code复制Controller层(API入口)
↓
Service层(业务逻辑)
↓
DAO层(数据访问)
以订单创建为例的代码结构:
java复制@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public Result createOrder(@RequestBody OrderDTO orderDTO) {
return orderService.createOrder(orderDTO);
}
}
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Transactional
public Result createOrder(OrderDTO dto) {
// 业务逻辑校验
// 库存检查
// 订单创建
}
}
@Mapper
public interface OrderMapper {
int insert(Order order);
}
2.3 数据库设计要点
核心表包括:
- 用户表(t_user):存储用户基本信息
- 菜品表(t_dish):菜品详情和库存
- 订单表(t_order):订单主信息
- 订单明细表(t_order_detail):订单与菜品关联
特别注意的点:
- 金额字段使用DECIMAL(10,2)避免精度丢失
- 订单号采用业务前缀+时间戳+随机数生成(如OD20230801123456)
- 建立适当的索引提升查询性能
3. 核心功能实现
3.1 用户认证与授权
采用JWT(JSON Web Token)实现无状态认证,流程如下:
- 用户登录成功后生成Token
- Token中包含用户ID和角色信息
- 前端将Token存入localStorage
- 每次请求携带Token进行鉴权
关键代码示例:
java复制public class JwtUtil {
private static final String SECRET = "your-secret-key";
private static final long EXPIRATION = 86400L; // 24小时
public static String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.claim("roles", userDetails.getAuthorities())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
// 验证和解析Token的方法...
}
3.2 菜品管理模块
实现要点:
- 图片上传使用阿里云OSS或本地存储
- 菜品分类采用树形结构存储
- 库存变更需要加锁处理
典型接口设计:
java复制@RestController
@RequestMapping("/api/dishes")
public class DishController {
@GetMapping
public PageResult<DishVO> listDishes(
@RequestParam(required = false) String name,
@RequestParam(required = false) Long categoryId,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
// 分页查询逻辑
}
@PostMapping
public Result addDish(@RequestBody DishDTO dishDTO) {
// 添加菜品逻辑
}
}
3.3 订单处理流程
订单状态机设计:
code复制待支付 → 已支付 → 配送中 → 已完成
↘ 已取消
关键业务逻辑:
- 创建订单时需要检查库存
- 支付成功后扣减库存
- 超时未支付自动取消订单
使用Spring的@Transactional确保数据一致性:
java复制@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public Result createOrder(OrderDTO orderDTO) {
// 1. 检查库存
// 2. 扣减库存
// 3. 创建订单
// 4. 生成支付信息
}
}
4. 项目部署与优化
4.1 后端部署方案
推荐两种部署方式:
- 传统部署:
- 打包:mvn clean package
- 运行:java -jar your-application.jar
- 配置:application-prod.yml
- Docker部署:
dockerfile复制FROM openjdk:8-jdk-alpine
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
4.2 前端部署要点
- 生产环境构建:
bash复制npm run build
- Nginx配置示例:
nginx复制server {
listen 80;
server_name your-domain.com;
location / {
root /path/to/dist;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:8080;
}
}
4.3 性能优化建议
- 数据库层面:
- 合理设计索引
- 使用连接池(如HikariCP)
- 复杂查询考虑缓存
- 代码层面:
- 避免N+1查询问题
- 使用DTO进行数据传输
- 合理使用缓存(如Redis)
- 前端优化:
- 组件懒加载
- API请求节流
- 图片懒加载
5. 常见问题与解决方案
5.1 跨域问题处理
SpringBoot中配置全局CORS:
java复制@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
5.2 文件上传大小限制
在application.yml中配置:
yaml复制spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
5.3 日期时间处理
统一使用Java 8的LocalDateTime:
java复制@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
5.4 线上问题排查
推荐使用Arthas进行线上诊断:
- 查看方法调用耗时
- 监控JVM状态
- 动态修改日志级别
6. 项目扩展方向
6.1 微信小程序集成
通过微信开放平台API实现:
- 微信登录
- 微信支付
- 消息模板推送
6.2 数据统计分析
集成ECharts实现:
- 销售趋势分析
- 菜品销量排行
- 用户消费画像
6.3 智能推荐系统
基于用户历史订单:
- 协同过滤推荐
- 热门菜品推荐
- 时段特推菜品
在实际开发中,我遇到最棘手的问题是库存超卖问题。最终通过Redis分布式锁+数据库乐观锁的双重保障机制解决。核心代码如下:
java复制public Result createOrder(OrderDTO orderDTO) {
// 获取分布式锁
String lockKey = "product_" + productId;
try {
boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!locked) {
throw new BusinessException("系统繁忙,请稍后再试");
}
// 检查库存(使用乐观锁)
int affected = productMapper.reduceStockWithOptimisticLock(productId, quantity);
if (affected == 0) {
throw new BusinessException("库存不足");
}
// 创建订单...
} finally {
redisTemplate.delete(lockKey);
}
}
这个项目从技术选型到最终上线,让我深刻体会到合理架构设计的重要性。特别是在高并发场景下,一个小小的库存问题就可能引发严重的业务事故。建议开发者在实现基础功能后,一定要进行压力测试,及早发现潜在的性能瓶颈。
