实战篇 01. 达人探店 - 发布探店笔记学习文档

3 阅读3分钟

📚 实战篇 01. 达人探店 - 发布探店笔记学习文档

一、 业务场景介绍

“达人探店”的核心玩法是:用户去某家商户消费后,可以发布包含图片和文字的“探店笔记”(类似于发朋友圈或小红书)。其他用户可以查看这些笔记,并进行点赞、评论等互动。

在“发布探店笔记”这个首要环节中,主要包含两个核心动作:

  1. 上传图片: 用户在前端选择图片并上传,后端需要将图片保存起来,并返回图片的访问链接。
  2. 发布笔记: 用户填写标题、正文,关联商户,连同刚才的图片链接一起提交给后端,后端将其存入数据库。

二、 核心业务流程拆解

1. 图片上传接口 (uploadImage)

  • 接收请求: 前端会将图片以表单数据(MultipartFile)的形式发送给后端。

  • 保存图片: * 在真实的生产环境中,通常会使用第三方对象存储服务(如 阿里云 OSS、七牛云 等)。

    • 在我们的实战学习中,为了方便,通常会将图片保存在 Nginx 服务器的指定静态资源目录下(例如 /nginx-1.18.0/html/hmdp/imgs/)。
  • 返回路径: 图片保存成功后,后端需要生成一个该图片的相对或绝对访问路径,封装在 Result 中返回给前端,前端拿到路径后用于数据回显和后续的笔记提交。

2. 发布笔记接口 (saveBlog)

  • 接收请求: 前端将组装好的笔记数据(Blog 对象,包含 title, images, content, shopId 等)发送给后端。
  • 补充用户信息: 前端传过来的数据中往往不包含“是谁发的”。我们需要在后端通过拦截器保存的 ThreadLocal 来获取当前登录用户的 ID。
  • 保存入库: 将补全了用户 ID 的 Blog 对象调用 MyBatisPlus 的 save() 方法存入 tb_blog 数据库表中。
  • 返回结果: 返回生成的笔记 ID 给前端,代表发布成功。

三、 Java 后端代码实现思路

1. 图片上传核心代码逻辑

图片上传的难点在于生成唯一的文件名(防止图片重名被覆盖)以及目录的管理。

Java

@PostMapping("blog/upload")
public Result uploadImage(@RequestParam("file") MultipartFile image) {
    try {
        // 1. 获取原始文件名
        String originalFilename = image.getOriginalFilename();
        // 2. 生成唯一的新文件名 (可以使用 UUID,并拼接上原始文件后缀)
        String suffix = StrUtil.subAfter(originalFilename, ".", true);
        String name = UUID.randomUUID().toString(true) + "." + suffix;
        
        // 3. 将文件保存到 Nginx 的静态资源目录
        // 注意:这里的 SystemConstants.IMAGE_UPLOAD_DIR 需要配置为你本地的 nginx 对应目录
        File dest = new File(SystemConstants.IMAGE_UPLOAD_DIR, name);
        image.transferTo(dest);
        
        // 4. 返回图片的访问相对路径
        return Result.ok(name);
    } catch (IOException e) {
        log.error("图片上传失败", e);
        return Result.fail("图片上传失败");
    }
}

2. 保存笔记核心代码逻辑

这段逻辑非常纯粹,就是标准的单表插入操作,但一定要记得关联当前用户。

Java

@PostMapping("blog")
public Result saveBlog(@RequestBody Blog blog) {
    // 1. 获取当前登录用户
    // UserHolder 是我们之前封装的基于 ThreadLocal 的工具类
    Long userId = UserHolder.getUser().getId();
    
    // 2. 设置探店笔记的作者 ID
    blog.setUserId(userId);
    
    // 3. 保存探店笔记到数据库 (MyBatisPlus 提供的 save 方法)
    boolean isSuccess = blogService.save(blog);
    
    if(!isSuccess){
        return Result.fail("发布笔记失败!");
    }
    // 4. 返回笔记的 ID
    return Result.ok(blog.getId());
}

四、 学习总结与防坑指南

  1. 温故知新:saveBlog 方法中,我们再次使用了 UserHolder.getUser().getId()。这证明了我们之前设计的基于拦截器和 ThreadLocal 的用户鉴权机制是非常通用且强大的,在任何业务接口中都能随时无缝获取当前用户信息。
  2. Nginx 目录配置: 在做图片上传测试时,最容易踩的坑就是图片上传成功了,但前端页面刷不出来。这通常是因为 Nginx 的目录配置不对,或者上传的文件路径与 Nginx 的代理规则不匹配。一定要确保 Java 代码中写入的目录与 Nginx nginx.conf 中配置的静态资源拦截目录保持一致。