一.文件上传接口
整个程序的执行过程:浏览器传来图片到后端,后端将图片传到阿里云:

POST请求,请求路径是admin/common/upload,我们需要先创建一个CommonController
1.控制层开发commoncontroller
CommonController 类通过 @RestController 注解暴露为一个 RESTful 接口,主要提供文件上传功能。通过 @PostMapping("/upload"),定义了一个文件上传的接口 upload。该接口接收前端上传的文件,使用 MultipartFile 类型的 file 参数接收文件。首先,接口获取文件的原始文件名 originalFilename,然后通过 substring() 截取文件的后缀(例如 .jpg 或 .png)。接着,利用 UUID.randomUUID() 生成一个唯一的文件名 objectName,避免文件名冲突。生成的文件名与原始文件的后缀结合后,调用 AliOssUtil.upload() 方法将文件的字节流上传至阿里云 OSS,并返回文件的存储路径 filePath。
在文件上传过程中,接口通过 try-catch 块捕获可能出现的异常,例如文件读取或上传失败等。如果上传过程中没有出现异常,文件上传成功后,接口会使用 Result.success(filePath) 返回一个成功响应,携带上传后文件在阿里云 OSS 中的存储路径。若发生异常,则会捕获 IOException 并记录错误日志 log.error("文件上传失败", e),然后返回一个失败的响应 Result.error("MessageConstant.UPLOAD_FAILED"),告知前端上传失败。

2.OSS配置
AliOssProperties 类通过 @ConfigurationProperties(prefix = "sky.alioss") 注解从 application.properties 或 application.yml 中读取以 sky.alioss 为前缀的配置信息。这些配置信息包括:endpoint(阿里云 OSS 服务的访问域名)、accessKeyId(用于身份验证的阿里云访问密钥 ID)、accessKeySecret(用于身份验证的阿里云访问密钥 Secret)和 bucketName(存储桶名称)。这些配置项被自动注入到 AliOssProperties 类中的字段,并通过 @Component 注解使其成为 Spring 的一个组件,供其他部分使用。
AliOssUtil 类是一个工具类,提供了与阿里云 OSS 的交互功能,特别是文件上传。它包含一个 upload() 方法,接受文件的字节数据和目标文件名,并将文件上传到阿里云 OSS 存储桶。方法中首先使用 OSSClientBuilder 创建一个 OSSClient 实例,并通过该实例调用 putObject() 方法将文件上传到指定的 OSS 存储桶。上传成功后,生成文件的访问路径(https://bucketName.endpoint/objectName)并返回该路径。在上传过程中,AliOssUtil 会捕获并处理 OSSException 和 ClientException,并打印详细的错误信息。
最终在配置文件application.yml中进行配置





二.新增菜品接口
1.控制层DishController
DishController 是一个用于处理菜品相关请求的控制器,使用了 @RestController 来标记它是一个 RESTful 风格的控制器,并通过 @RequestMapping("/admin/dish") 定义了该控制器的基本请求路径前缀 /admin/dish。控制器内的 save() 方法处理菜品的新增操作,接受前端传来的 DishDTO 对象,并调用 DishService 的 saveWithFlavor() 方法来完成新增操作。在方法中,使用 @ApiOperation 注解对接口进行了描述,帮助生成接口文档,并通过日志 log.info("新增菜品:{}", dishDTO); 记录了操作过程中的关键信息。新增操作完成后,返回一个成功的 Result 对象,表示操作成功。

2.服务层方法及实现类
DishServiceImpl 类是 DishService 接口的实现类,主要用于处理菜品及口味的业务逻辑。在 saveWithFlavor() 方法中,首先通过 BeanUtils.copyProperties() 将 DishDTO 中的属性复制到 Dish 实体对象中,然后调用 dishMapper.insert(dish) 插入菜品数据。接着,通过 dish.getId() 获取菜品的 ID,并遍历菜品口味列表 flavors,将 dishId 设置到每个 DishFlavor 实体中。最后,调用 dishFlavorMapper.insertBatch(flavors) 批量插入口味数据。方法上使用了 @Transactional 注解,确保菜品和口味的数据插入操作要么全部成功,要么全部失败,保证数据的一致性。


3.Mapper层开发
DishFlavorMapper 接口用于管理菜品口味数据,提供了一个方法 insertBatch(List<DishFlavor> flavors) 来批量插入口味数据。方法体内使用 MyBatis 注解 @Mapper 来声明该接口是 MyBatis 的映射接口。在 insertBatch() 方法中,使用了 <insert> 标签的 SQL 映射,向 dish_flavor 表插入多条数据。<foreach> 标签用于迭代传入的口味列表 flavors,并将每个口味的 dishId、name 和 value 插入到表中。
在 DishFlavorMapper.xml 中,insertBatch 是一个批量插入口味数据的方法。使用 <insert> 标签来定义插入语句,<foreach> 标签遍历传入的 flavors 列表,生成多条插入语句。每一条插入语句都将 dishId、name 和 value 插入到 dish_flavor 表中。
DishMapper.xml 中,insert 是一个插入菜品数据的方法。通过 useGeneratedKeys="true" 和 keyProperty="id",该配置能够使数据库自动生成的主键(菜品的 ID)回填到 Dish 实体中。在 insert 语句中,菜品的各种字段(如 name、categoryId、price、image 等)会被插入到 dish 表中。@AutoFill 注解确保在插入时自动填充创建时间、更新时间等公共字段。


