视频加载失败

苍穹外卖 Day02:菜品新增、文件上传与 AutoFill 补全

634 字
3 分钟
苍穹外卖 Day02:菜品新增、文件上传与 AutoFill 补全

菜品新增(含口味)#

入口 DishController.save,业务落在 DishServiceImpl.saveWithFlavor:

  1. BeanUtils.copyProperties(dishDTO, dish) 做 DTO 到实体的属性拷贝,调 dishMapper.insert(dish) 落主表;insert 标签配置 useGeneratedKeys=true keyProperty="id" 回填自增主键。
  2. 口味列表非空时,flavors.forEach(df -> df.setDishId(dishId)) 回填外键,再走 dishFlavorMapper.insertBatch(flavors) 批量插入。
  3. 方法加 @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 的处理链:

  1. MultipartFile 接收文件,取原始文件名后缀 substring(lastIndexOf("."))。
  2. UUID.randomUUID() + extension 构造新文件名,防止重名覆盖。
  3. 目录分隔符防御(路径已有 / 或 \ 则不再拼接)+ dir.mkdirs() + file.transferTo(new File(path+name)) 写盘。
  4. 返回 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。

代码锚点定位#

锚点路径
菜品新增 Controllersky-server/.../controller/admin/DishController.java
菜品 Service 业务sky-server/.../service/impl/DishServiceImpl.java
菜品主表 Mappersky-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/
作者
RK
发布于
2026-08-20
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
RK
Long may the sunshine
公告
Long may the sunshine
分类
标签
最新动态
站点天气
天气加载中…
站点统计
文章
27
分类
6
标签
59
总字数
39,139
篝火已燃
0 天
最后活动
0 天前
每日一签