08-黑马点评项目发布笔记和查看笔记功能的实现

news2025/1/16 16:15:49

发布笔记

数据模型

tb_blog探店笔记表,包含笔记的标题、文字、图片等

在这里插入图片描述

tb_blog探店笔记表对应的实体类

  • 增加用户图标和和用户姓名以及是否被点赞过了的字段,这些字段不属于Blog表只是为了实现在展示笔记的时候同时展示用户的信息
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_blog")
public class Blog implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 商户id
     */
    private Long shopId;
    /**
     * 用户id
     */
    private Long userId;
    /**
     * 用户图标,不属于Blog表中的字段
     */
    @TableField(exist = false)
    private String icon;
    /**
     * 用户姓名,不属于Blog表中的字段
     */
    @TableField(exist = false)
    private String name;
    /**
     * 是否点赞过了
     */
    @TableField(exist = false)
    private Boolean isLike;
    /**
     * 标题
     */
    private String title;
    /**
     * 探店的照片,最多9张,多张以","隔开
     */
    private String images;
    /**
     * 探店的文字描述
     */
    private String content;
    /**
     * 点赞数量
     */
    private Integer liked;
    /**
     * 评论数量
     */
    private Integer comments;
    /**
     * 创建时间
     */
    private LocalDateTime createTime;
    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}

界面原型

用户发布笔记时选择要上传的图片,笔记标题和笔记内容以及关联的商户

在这里插入图片描述

后端处理请求

第一步: 在UploadController中实现图片上传的功能,实际开发中图片一般会放在nginx上或者是云存储上

public class SystemConstants {
    // 指定图片所在的地址,这里我们放在自己的nginx服务所在的目录
    public static final String IMAGE_UPLOAD_DIR = "D:\\dev\\nginx-1.18.0\\html\\hmdp\\imgs\\";
    // 指定用户昵称的前缀
    public static final String USER_NICK_NAME_PREFIX = "user_";
    // 指定分页查询的默认页数
    public static final int DEFAULT_PAGE_SIZE = 5;
    // 指定分页查询的最大页数
    public static final int MAX_PAGE_SIZE = 10;
}
@Slf4j
@RestController
@RequestMapping("upload")
public class UploadController {
    @PostMapping("blog")
    public Result uploadImage(@RequestParam("file") MultipartFile image) {
        try {
            // 获取上传文件的文件名称
            String originalFilename = image.getOriginalFilename();
            // 生成新文件名,处理文件重名问题
            String fileName = createNewFileName(originalFilename);
            // 保存文件到自己指定的位置下
            image.transferTo(new File(SystemConstants.IMAGE_UPLOAD_DIR, fileName));
            // 返回文件名作为图片的地址
            log.debug("文件上传成功,{}", fileName);
            return Result.ok(fileName);
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }
}

// 更改上传的文件名并存储到自己指定的目录下
private String createNewFileName(String originalFilename) {
    // 获取后缀
    String suffix = StrUtil.subAfter(originalFilename, ".", true);
    // 生成目录
    String name = UUID.randomUUID().toString();
    int hash = name.hashCode();
    int d1 = hash & 0xF;
    int d2 = (hash >> 4) & 0xF;
    // 判断目录是否存在
    File dir = new File(SystemConstants.IMAGE_UPLOAD_DIR, StrUtil.format("/blogs/{}/{}", d1, d2));
    if (!dir.exists()) {
        dir.mkdirs();
    }
    // 生成文件名
    return StrUtil.format("/blogs/{}/{}/{}.{}", d1, d2, name, suffix);
}

第二步: 在BlogController中将探店笔记存储到数据库

@RestController
@RequestMapping("/blog")
public class BlogController {
   @Resource
   private IBlogService blogService;
   @PostMapping
   public Result saveBlog(@RequestBody Blog blog) {
       // 获取登录用户的Id
       UserDTO user = UserHolder.getUser();
       // 设置发布博文的用户Id
       blog.setUserId(user.getId());
       // 保存探店博文
       blogService.save(blog);
       // 返回博文的Id
       return Result.ok(blog.getId());
   }
}

查看探店笔记

界面原型

需求: 点击首页的某个探店笔记会进入笔记详情页面展示,主要展示笔记的信息和发布笔记的用户信息

在这里插入图片描述

查看用户笔记

如何实现在展示笔记的时候同时展示用户的信息的两种实现方式

  • 在Blog类中存储user属性,根据Blog对象中的userIdtb_user表中查询用户信息并封装到User对象并赋值给Blog对象的user属性

  • 在Blog中增加user的相关属性icon和name,由于这两个属性只在Blog类中不属于tb_blog表的字段,所以需要在属性上使用@TableField(exist = false)注解

第一步: 在BlogController中调用BlogService中的业务方法queryBlogById

@GetMapping("/{id}")
public Result queryBlogById(@PathVariable Integer id){
    return blogService.queryBlogById(id);
}	

第二步:在Service接口的实现类BlogServiceImpl中实现查看笔记信息和发布笔记的用户信息的业务逻辑

public interface IBlogService extends IService<Blog> {
    Result queryBlogById(Integer id);
}

@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
    @Resource
    private IUserService userService;
    @Override
    public Result queryBlogById(Integer id) {
        // 1.根据ID查询Blog
        Blog blog = getById(id);
        if (blog == null) {
            return Result.fail("评价不存在或已被删除");
        }
        // 2.查询发表Blog的用户
        queryBlogUser(blog);
        return Result.ok(blog);
    }
    // 由于查看用户信息这个操作比较通用,所以这里封装成了一个方法
    private void queryBlogUser(Blog blog) {
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }
}

查看热门笔记

当我们访问首页的时候会根据用户点赞数量降序分页查询多个热门笔记(包含用户昵称和头像)

@GetMapping("/hot")
public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
    return blogService.queryHotBlog(current);
}
@Resource
private IUserService userService;
@Override
public Result queryHotBlog(Integer current) {
    // 根据用户点赞数量降序分页查询热门笔记
    Page<Blog> page = query()
        .orderByDesc("liked")
        .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
    // 获取查询到的所有热门笔记信息
    List<Blog> records = page.getRecords();
    // 查询每个热门笔记对应的用户昵称和头像
    /*records.forEach(blog ->{
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    });*/
   	// 将查询用户昵称和图标逻辑封装成一个方法
    /*
    records.forEach(blog->{
    	queryBlogUser(blog);
    });
    */
    records.forEach(this::queryBlogUser);
    // 返回查询到的所有笔记信息包含用户的昵称和图标
    return Result.ok(records);
}
private void queryBlogUser(Blog blog) {
    Long userId = blog.getUserId();
    User user = userService.getById(userId);
    blog.setName(user.getNickName());
    blog.setIcon(user.getIcon());
}

查看自己发布的笔记

根据当前登录用户的Id分页查询用户自己发布的所有笔记并且不用包含用户昵称和头像

@GetMapping("/of/me")
public Result queryMyBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
    // 获取当前登录用户的Id
    UserDTO user = UserHolder.getUser();
    // 根据用户Id分页查询用户自己发布的所有笔记
    Page<Blog> page = blogService.query()
        .eq("user_id", user.getId()).page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
    // 返回查询到的笔记信息不用包含用户昵称和头像
    List<Blog> records = page.getRecords();
    return Result.ok(records);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1225363.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

<MySQL> 什么是JDBC?如何使用JDBC进行编程?

目录 一、JDBC是什么&#xff1f; 二、JDBC常用接口和类 2.1 DataSource 2.2 Connection 2.3 Statement 2.4 ResultSet 三、JDBC的使用 3.1 获得数据库驱动包 3.2 添加到项目依赖 3.3 描述数据库服务器 3.4 建立数据库连接 3.6 执行SQL语句和接收返回数据 3.7 释放…

利用 Pandoc + ChatGPT 优雅地润色论文,并保持 Word 公式格式:Pandoc将Word和LaTeX文件互相转化

论文润色完美解决方案&#xff1a;Pandoc 与 ChatGPT 的强强联合 写在最前面其他说明 一、通过 Pandoc 将 Word 转换为 LaTeX 的完整指南步骤 1: 安装 PandocWindows:macOS:Linux: 步骤 2: 准备 Word 文档步骤 3: 转换文档步骤 4: 检查并调整输出步骤 5: 编译 LaTeX 文档总结 二…

企业制作产品操作手册,真的很有必要吗?

企业制作产品操作手册通常是必不可少的。一份详细的指南可以使得用户或操作员能够了解如何正确地使用产品。然而&#xff0c;有些企业可能会怀疑这一做法的必要性&#xff0c;认为这只是一项额外的成本和劳动力投入。但是&#xff0c;企业产品操作手册是提高产品使用效率和用户…

【c++】——类和对象(中)——实现完整的日期类(优化)万字详细解疑答惑

作者:chlorine 专栏:c专栏 赋值运算符重载()()():实现完整的日期类(上) 我走的很慢&#xff0c;但我从不后退。 【学习目标】 日期(- - --)天数重载运算符 日期-日期 返回天数 对日期类函数进行优化(不符合常理的日期&#xff0c;负数&#xff0c;const成员)c中重载输入cin和输…

基于STM32的外部中断(EXTI)在嵌入式系统中的应用

外部中断&#xff08;External Interrupt&#xff0c;EXTI&#xff09;是STM32嵌入式系统中常见且重要的功能之一。它允许外部事件&#xff08;例如按键按下、传感器触发等&#xff09;通过适当的引脚触发中断&#xff0c;从而应用于各种嵌入式系统中。在STM32微控制器中&#…

Spring Boot - filter 的顺序

定义过滤器的执行顺序 1、第一个过滤器 import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; impor…

二维码智慧门牌管理系统升级解决方案:高效运营,信息尽在掌握

文章目录 前言一、升级要点二、方案优势三、应用场景四、客户案例 前言 在这个日新月异的时代&#xff0c;二维码智慧门牌管理系统已经成为了各行各业的标配。为了更好地满足用户需求&#xff0c;提升运营效率&#xff0c;我们推出了全新的升级解决方案。这个方案将让你轻松掌…

<C++>类和对象下|初始化列表|explicit static|友元|内部类|匿名对象|构造函数的优化

文章目录 1. 初始化列表2. explicit关键字3. 友元3.1 友元函数3.2 友元类 4. static关键字4.1 概念4.2 特性 5.内部类5.1 概念5.2 特性 6. 匿名对象7. 拷贝构造时的优化 1. 初始化列表 在类的构造函数体中&#xff0c;对成员属性写的操作叫做赋值&#xff0c;那么成员的初始化…

springBoot中starter

springBoot项目中引入starter 项目引入xxljob&#xff0c;仅需要导入对应的starter包&#xff0c;即可进行快速开发 <dependency><groupId>com.ydl</groupId><artifactId>xxl-job-spring-boot-starter</artifactId><version>0.0.1-SNAPS…

Ubuntu20.04 安装微信 【优麒麟的镜像源方式安装】

缺点&#xff1a;是网页版本的嵌入&#xff0c;功能少。 推荐wine方式安装&#xff1a;Ubuntu20.04 安装微信 【wine方式安装】推荐 从优麒麟的镜像源安装原生微信 应用下载-优麒麟&#xff5c;Linux 开源操作系统 新建文件software.list sudo vi /etc/apt/sources.list.d/…

WordPress主题WoodMart v7.3.2 WooCommerce主题和谐汉化版下载

WordPress主题WoodMart v7.3.2 WooCommerce主题和谐汉化版下载 WoodMart是一款出色的WooCommerce商店主题&#xff0c;它不仅提供强大的电子商务功能&#xff0c;还与流行的Elementor页面编辑器插件完美兼容。 主题文件在WoodMart Theme/woodmart.7.3.2.zip&#xff0c;核心在P…

Golang起步篇(Windows、Linux、mac三种系统安装配置go环境以及IDE推荐以及入门语法详细释义)

Golang起步篇 Golang起步篇一. 安装Go语言开发环境1. Wondows下搭建Go开发环境(1). 下载SDK工具包(2). 解压下载的压缩包&#xff0c;放到特定的目录下&#xff0c;我一般放在d:/programs下(路径不能有中文或者特殊符号如空格等)(3). 配置环境变量步骤1&#xff1a;先打开环境变…

python自动化标注工具+自定义目标P图替换+深度学习大模型(代码+教程+告别手动标注)

省流建议 本文针对以下需求&#xff1a; 想自动化标注一些目标不再想使用yolo想在目标检测/语意分割有所建树计算机视觉项目想玩一玩大模型了解自动化工具了解最前沿模型自定义目标P图替换… 确定好需求&#xff0c;那么我们发车&#xff01; 实现功能与结果 该模型将首先…

【SQL server】数据库、数据表的创建

创建数据库 --如果存在就删除 --所有的数据库都存在sys.databases当中 if exists(select * from sys.databases where name DBTEST)drop database DBTEST--创建数据库 else create database DBTEST on --数据文件 (nameDBTEST,--逻辑名称 字符串用单引号filenameD:\DATA\DBT…

uni-app(1)pages. json和tabBar

第一步 在HBuilderX中新建项目 填写项目名称、确定目录、选择模板、选择Vue版本&#xff1a;3、点击创建 第二步 配置pages.json文件 pages.json是一个非常重要的配置文件&#xff0c;它用于配置小程序的页面路径、窗口表现、导航条样式等信息。 右键点击pages&#xff0c;按…

C语言进阶第十课 --------文件的操作

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

从多表连接视图对比人大金仓和Oracle

KING BASE 信息时代&#xff0c;数据是驱动业务决策和创新的核心资源。然而&#xff0c;随着数据量的不断增加&#xff0c;有效地处理和整合数据的过程变得愈发复杂。这时&#xff0c;多表连接视图悄然走进数据库世界&#xff0c;不仅能够将多个表中的数据整合在一起&#xff0…

代码随想录算法训练营第四十八天|121. 买卖股票的最佳时机 122.买卖股票的最佳时机II

文档讲解&#xff1a;代码随想录 视频讲解&#xff1a;代码随想录B站账号 状态&#xff1a;看了视频题解和文章解析后做出来了 121. 买卖股票的最佳时机 class Solution:def maxProfit(self, prices: List[int]) -> int:if len(prices) 0:return 0dp [[0] * 2 for _ in r…

二叉树前序,中序,后序遍历

前序遍历&#xff08;递归&#xff09;&#xff1a; 中序遍历&#xff08;递归&#xff09;&#xff1a;