基于 Java + Spring Boot + MySQL 的在线外卖订餐点餐网站系统设计与实现
引言
在线外卖订餐系统是一种典型的电子商务应用,允许用户浏览菜单、下订单、支付,并管理订单状态。该系统使用 Java 作为核心语言,Spring Boot 作为后端框架(提供快速开发、微服务支持),MySQL 作为数据库(高效、可靠)。前端可采用 JSP(简单集成)或 Vue.js(现代交互),但本设计以 JSP 为例,便于后端开发者快速实现。根据 2025-2026 年开发实践,这种架构适合中小型项目,能处理高并发订单,支持移动端适配。
系统目标:
- 用户端:注册/登录、浏览餐厅/菜单、下单、支付、查看订单。
- 商家端:管理菜单、处理订单。
- 管理员端:用户/商家审核、数据统计。
- 扩展:集成支付(如支付宝/微信)、地图定位、推送通知。
系统需求分析
功能需求
- 用户模块:注册、登录、个人信息管理、订单跟踪。
- 餐厅/菜单模块:浏览餐厅、搜索菜品、购物车。
- 订单模块:下单、支付、取消、评价。
- 商家模块:上传菜单、查看订单、更新状态。
- 管理员模块:审核、统计报表。
- 其他:搜索推荐、优惠券、地址管理。
非功能需求
- 性能:支持 1000+ 并发(使用 Redis 缓存)。
- 安全:JWT 认证、SQL 注入防护。
- 可扩展:模块化设计,支持微服务拆分。
- 兼容:Web/移动端适配。
系统架构设计
采用前后端分离架构,后端提供 RESTful API,前端消费数据。整体采用 MVC 模式(Model-View-Controller)。
架构图
以下是典型在线外卖系统的架构示意图(参考行业标准设计):
- 后端:Spring Boot + MyBatis-Plus(ORM) + Spring Security(安全) + Redis(缓存)。
- 前端:JSP/HTML + Bootstrap(UI) + JavaScript/Ajax(交互)。
- 数据库:MySQL,ER 图参考:
- 部署:Docker 容器化,Nginx 代理前端。
数据库设计
使用 MySQL,设计了以下核心表(基于 E-R 模型):
| 表名 | 主要字段 | 描述 |
|---|---|---|
| users | id (PK), username, password (加密), role (user/merchant/admin), address | 用户表 |
| restaurants | id (PK), name, address, owner_id (FK users), rating | 餐厅表 |
| menu_items | id (PK), restaurant_id (FK), name, price, description, image_url | 菜单项表 |
| orders | id (PK), user_id (FK), restaurant_id (FK), total_price, status (pending/paid/delivered), create_time | 订单表 |
| order_items | id (PK), order_id (FK), menu_item_id (FK), quantity | 订单详情表 |
| comments | id (PK), order_id (FK), user_id (FK), content, rating | 评论表 |
- 关系:用户一对多订单,餐厅一对多菜单,订单一对多订单项。
- 索引:订单表 status 和 create_time 索引,支持快速查询。
- 扩展:添加 payment_logs 表支持支付记录。
后端实现(Spring Boot)
后端使用 Spring Boot 构建 RESTful API。核心依赖如前述 pom.xml。
1. 用户认证(JWT)
- SecurityConfig.java(配置 JWT 过滤器):
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
- AuthController.java(登录/注册):
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody LoginRequest req) {
// 验证密码,生成 JWT
String token = jwtService.generateToken(req.getUsername());
return ResponseEntity.ok(token);
}
}
2. 菜谱/订单管理
- RecipeController.java(示例 API):
@RestController
@RequestMapping("/api/recipes")
public class RecipeController {
@Autowired
private RecipeService service;
@GetMapping
public Page<Recipe> search(@RequestParam String keyword, @RequestParam int page) {
return service.searchRecipes(keyword, page, 10);
}
@PostMapping("/order")
public Order placeOrder(@RequestBody OrderRequest req) {
// 处理订单逻辑
return service.createOrder(req);
}
}
- Service层使用 MyBatis-Plus:
@Service
public class RecipeService extends ServiceImpl<RecipeMapper, Recipe> {
public Page<Recipe> searchRecipes(String keyword, int page, int size) {
QueryWrapper<Recipe> wrapper = new QueryWrapper<>();
wrapper.like("name", keyword);
return this.page(new Page<>(page, size), wrapper);
}
}
3. 文件上传(菜单图片)
- UploadController.java:
@PostMapping("/api/upload")
public String upload(@RequestParam("file") MultipartFile file) {
// 保存文件,返回 URL
String fileName = UUID.randomUUID() + ".jpg";
file.transferTo(new File("/path/to/storage/" + fileName));
return "/images/" + fileName;
}
前端实现(JSP 或 Vue)
假设使用 JSP(简单集成 Spring Boot),或 Vue(现代 UI)。
JSP 示例(Home.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>首页</title>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>欢迎来到外卖平台</h1>
<form action="/api/recipes" method="get">
<input name="keyword" placeholder="搜索菜品">
<button type="submit">搜索</button>
</form>
<!-- 使用 JSTL 循环显示菜谱 -->
<c:forEach items="${recipes}" var="recipe">
<div class="card">
<img src="${recipe.imageUrl}" alt="${recipe.name}">
<h3>${recipe.name}</h3>
<p>${recipe.description}</p>
</div>
</c:forEach>
</div>
</body>
</html>
Vue 示例(如果采用前后端分离)
- Home.vue:
<template>
<el-input v-model="keyword" placeholder="搜索菜品" />
<el-button @click="search">搜索</el-button>
<el-row>
<el-col v-for="recipe in recipes" :key="recipe.id">
<el-card>
<img :src="recipe.imageUrl" />
<h3>{{ recipe.name }}</h3>
</el-card>
</el-col>
</el-row>
</template>
<script setup>
import { ref } from 'vue'
import api from '@/api'
const keyword = ref('')
const recipes = ref([])
const search = async () => {
const res = await api.get('/api/recipes', { params: { keyword: keyword.value } })
recipes.value = res.data
}
</script>
部署与测试
- 部署:后端 mvn package 生成 Jar,运行 java -jar app.jar;前端静态文件用 Nginx 代理。
- 测试:单元测试(JUnit),集成测试(Postman),功能测试(Selenium)。
- 优化:添加 Redis 缓存热门菜谱,集成支付宝支付 SDK。
结论
该系统实现了高效的外卖订餐功能,代码模块化,便于维护。完整源码可在 GitHub 搜索类似项目(如“Online-Food-Delivery”)。 如果需要源码下载或扩展(如集成支付),请提供更多细节!