作为一个长期混迹在美食圈和程序员圈的双料爱好者,我一直在寻找将两个爱好结合的机会。去年用SpringBoot+Vue+MySQL搭建的这个美食分享平台,算是我对"代码烹饪"的一次实践。这个平台本质上是一个垂直领域的社交应用,核心解决三个问题:
技术选型上,后端采用SpringBoot 2.7 + MyBatis Plus的组合,前端用Vue3 + Element Plus,数据库是MySQL 8.0。这套技术栈的选择基于以下考量:
提示:实际开发中发现,Element Plus的Upload组件需要特别处理跨域问题,建议在后端配置CORS过滤器而非在前端代理
采用经典的前后端分离模式,通过JSON进行数据交互。这种架构的优势在于:
接口设计遵循RESTful规范,但做了适度灵活调整。例如美食列表接口:
java复制@GetMapping("/foods")
public Result<List<FoodVO>> getFoodList(
@RequestParam(required = false) Integer page,
@RequestParam(required = false) Integer size,
@RequestParam(required = false) String keyword) {
// 分页查询逻辑
}
核心表包括:
特别注意的点:
图片上传是美食平台的核心功能,实现方案:
java复制@PostMapping("/upload")
public Result<List<String>> uploadImages(
@RequestParam("files") MultipartFile[] files) {
List<String> urls = new ArrayList<>();
for (MultipartFile file : files) {
// 1. 校验文件类型(仅允许jpg/png)
// 2. 压缩图片(使用Thumbnails库)
// 3. 上传到OSS
urls.add(ossClient.upload(compressedImage));
}
return Result.success(urls);
}
踩坑记录:
采用混合推荐策略:
SQL示例:
sql复制SELECT f.* FROM food f
LEFT JOIN user_behavior ub ON f.id = ub.food_id
WHERE ub.user_id IN (
SELECT similar_user_id FROM user_similarity
WHERE user_id = #{currentUserId}
)
ORDER BY (f.like_count*0.3 + f.view_count*0.1) DESC
LIMIT 10
采用多级缓存架构:
缓存更新策略:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
code复制
## 5. 安全防护方案
### 5.1 认证与授权
采用JWT + 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()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()));
}
}
关键安全措施:
java复制@Bean
public FilterRegistrationBean<LogFilter> logFilter() {
FilterRegistrationBean<LogFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new LogFilter());
registration.addUrlPatterns("/*");
return registration;
}
使用Docker Compose编排服务:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:6
backend:
build: ./backend
ports:
- "8080:8080"
现象:前端报413 Request Entity Too Large
解决:
nginx复制client_max_body_size 20M;
yaml复制spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 20MB
通过EXPLAIN分析发现未走索引:
sql复制-- 优化前
SELECT * FROM food WHERE title LIKE '%火锅%';
-- 优化后
SELECT * FROM food WHERE title LIKE '火锅%'
CREATE INDEX idx_title ON food(title);
这个项目从技术角度看不算复杂,但完整走完设计、开发、上线的全流程后,最大的体会是:业务逻辑的严谨性比技术炫技更重要。比如最初设计的评论功能没有考虑删除场景,导致后来不得不做数据迁移。建议大家在设计阶段多画状态转换图,把各种边界情况考虑清楚。