苍穹外卖 Day02:菜品新增、文件上传与 AutoFill 补全
634 字
3 分钟
苍穹外卖 Day02:菜品新增、文件上传与 AutoFill 补全
菜品新增(含口味)
入口 DishController.save,业务落在 DishServiceImpl.saveWithFlavor:
BeanUtils.copyProperties(dishDTO, dish)做 DTO 到实体的属性拷贝,调dishMapper.insert(dish)落主表;insert 标签配置useGeneratedKeys=true keyProperty="id"回填自增主键。- 口味列表非空时,
flavors.forEach(df -> df.setDishId(dishId))回填外键,再走dishFlavorMapper.insertBatch(flavors)批量插入。 - 方法加
@Transactional包裹主表与口味表操作,保证一致性;Controller 返回Result.success()。
口味批量插入依赖 mapper XML 的 foreach 动态 SQL 拼接。
主键回填原理
useGeneratedKeys=true keyProperty="id" 的生效机制:MyBatis 执行 insert 后调用 JDBC 的 getGeneratedKeys() 拿到数据库自增 ID,再反射回填到实体属性;Service 层接着 Long dishId = dish.getId() 就能拿到主键,供口味表回填外键。对应代码是 DishMapper.xml insert 标签的配置,加上 DishServiceImpl 里取 id 的那一行。
不用 useGeneratedKeys 的替代方案:
selectKey:在 insert 前/后执行二次查询取主键- 雪花算法 / UUID 手动预生成 ID 再插入
通用文件上传(本地存储)
CommonController.upload 的处理链:
MultipartFile接收文件,取原始文件名后缀substring(lastIndexOf("."))。UUID.randomUUID() + extension构造新文件名,防止重名覆盖。- 目录分隔符防御(路径已有
/或\则不再拼接)+dir.mkdirs()+file.transferTo(new File(path+name))写盘。 - 返回
Result.success("/upload/" + objectName)供前端 img src 直接使用;IOException 返回Result.error。
上传目录从配置读取,application.yml:
sky: file: upload-path: D:/upload/注入方式为 @Value("${sky.file.upload-path}")。
静态资源映射
WebMvc 配置类里注册两类资源映射:
/doc.html与/webjars/**:接口文档(knife4j)相关资源/upload/**:映射到file:+ uploadPath,让上传到磁盘的文件可以通过 URL 直接访问;路径统一补了尾部分隔符,防止配置漏斜杠时 404
AutoFill 切面补全
前一天留下的切面填充逻辑补完,落在 AutoFillAspect.autoFill:
- 切入点:
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)") @Before("autoFillPointCut()")通知内:- 从
MethodSignature取方法上的AutoFill注解,annotation.value()得到OperationType joinPoint.getArgs()取实体(首个参数),准备LocalDateTime.now()与BaseContext.getCurrentId()- INSERT 反射 set 4 个字段(createTime/createUser/updateTime/updateUser);UPDATE 只 set updateTime/updateUser 两个字段
- 反射调用的方法名来自
AutoFillConstant常量(SET_CREATE_TIME / SET_CREATE_USER / SET_UPDATE_TIME / SET_UPDATE_USER)
- 从
- 参数数组为空时记日志后直接
return,防止args[0]触发 NPE
三处隐患修复
AutoFillAspect:空参数提前 return(防 NPE)DishFlavorMapper.xml:<foreach>补separator=",",防止多条口味拼出 SQL 语法错误WebMvcConfiguration:addResourceLocations统一补尾分隔符,防止配置漏斜杠时/upload/**404
修复后 mvn compile BUILD SUCCESS。
代码锚点定位
| 锚点 | 路径 |
|---|---|
| 菜品新增 Controller | sky-server/.../controller/admin/DishController.java |
| 菜品 Service 业务 | sky-server/.../service/impl/DishServiceImpl.java |
| 菜品主表 Mapper | sky-server/.../mapper/DishMapper.java + resources/mapper/DishMapper.xml |
| 口味批量插入 | sky-server/.../mapper/DishFlavorMapper.java + resources/mapper/DishFlavorMapper.xml |
| 通用上传 | sky-server/.../controller/admin/CommonController.java |
| 静态资源映射 | sky-server/.../config/WebMvcConfiguration.java |
| AutoFill 注解 | sky-server/.../annotation/AutoFill.java |
| AutoFill 切面 | sky-server/.../aspect/AutoFillAspect.java |
| 上传目录配置 | sky-server/src/main/resources/application.yml(sky.file.upload-path) |
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
苍穹外卖 Day02:菜品新增、文件上传与 AutoFill 补全
https://ryuki.icu/posts/sky-takeout-day02/相关文章智能推荐
1
苍穹外卖 Day04:用户端订单与模拟支付
项目实战用户端下单、模拟支付、历史订单分页查询的实现,以及套餐 Mapper 起步。
2
苍穹外卖 Day01:员工模块与分类管理、AutoFill
项目实战苍穹外卖第一天:员工模块与分类管理落地,AutoFill 公共字段自动填充方案定型
3
苍穹外卖 Day06:操作日志、RBAC 权限与订单链路改造
项目实战课程主线收尾后的自驱改造:AOP 操作日志落库、注解式 RBAC 拦截器、订单状态机加乐观锁、Redisson 延迟队列精准关单、布隆过滤器防缓存穿透。
4
苍穹外卖 Day03:菜品 CRUD、店铺状态与微信登录
项目实战苍穹外卖第三天:菜品模块完整增删改查、Redis 店铺营业状态、微信小程序登录
5
苍穹外卖 Day05:数据统计、定时任务与 JWT 拦截器
项目实战营业额/用户/订单统计报表与工作台、定时任务清理超时订单、用户端 JWT 拦截器落地。
随机文章随机推荐





















