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

发布笔记

数据模型

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 {@Resourceprivate IBlogService blogService;@PostMappingpublic Result saveBlog(@RequestBody Blog blog) {// 获取登录用户的IdUserDTO user = UserHolder.getUser();// 设置发布博文的用户Idblog.setUserId(user.getId());// 保存探店博文blogService.save(blog);// 返回博文的Idreturn 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 {@Resourceprivate IUserService userService;@Overridepublic Result queryBlogById(Integer id) {// 1.根据ID查询BlogBlog 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) {// 获取当前登录用户的IdUserDTO 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.mzph.cn/news/155979.shtml

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

相关文章

使用sed命令进行文本处理示例

文章目录 前言查找并替换操作在文件中添加文本删除文件中的文本高亮显示文件中的文本 转载请标明出处&#xff1a; https://bigmaning.blog.csdn.net/article/details/134539923 本文出自:【BigManing的博客】 前言 当我们需要在Linux系统中处理文本文件时&#xff0c;经常需要…

包装类型的缓存机制

Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。 Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128&#xff0c;127] 的相应类型的缓存数据&#xff0c;Character 创建了数值在 [0,127] 范围的缓存数据&#xff0c;Boolean 直接返回 True or Fal…

Vue框架学习笔记——v-bind数据单向绑定和v-model数据双向绑定

文章目录 v-bind&#xff0c;数据单向绑定简写形态&#xff08;省略v-bind&#xff0c;只留冒号&#xff09;示例一&#xff08;将输入框数据改为&#xff1a;哈哈哈哈哈&#xff09;&#xff1a;实例二&#xff08;将Vue实例中的name改为字符串&#xff1a;"单向绑定&quo…

多模态大模型训练数据集汇总介绍

RefCOCO、RefCOCO、RefCOCOg 这三个是从MS-COCO中选取图像得到的数据集&#xff0c;数据集中对所有的 phrase 都有 bbox 的标注。 RefCOCO 共有19,994幅图像&#xff0c;包含142,209个引用表达式&#xff0c;包含50,000个对象实例。RefCOCO 共有19,992幅图像&#xff0c;包含1…

Mybatis Plus分页实现逻辑整理(结合芋道整合进行解析)

Mybatis Plus分页实现逻辑整理&#xff08;结合芋道整合进行解析&#xff09; 我希望如春天般的你&#xff0c;身着白色的婚纱&#xff0c;向我奔赴而来&#xff0c;我愿意用全世界最温情的目光&#xff0c;朝着你的方向望去——姗姗来迟。 1.背景介绍 https://baomidou.com/p…

【gpts】学算法题[缺失的第一个正数](https://leetcode.cn/problems/first-missing-positive/)

给出你的题解 (https://leetcode.cn/problems/first-missing-positive/) public class Solution { public int firstMissingPositive(int[] nums) {int len nums.length;for (int i 0; i < len; i) {while (nums[i] > 0 && nums[i] < len && nums…

有依次对应关系的数组X、Y、Z,如何排序其中一个X数组,使得另外的数组还与排序完成后的数组相对应(C语言实现)

1. 目的 有依次对应关系的数组X、Y、Z&#xff0c;排序其中一个X数组&#xff0c;使得另外的数组还与排序完成后的数组相对应&#xff0c;并打印出排序完成后的X、Y、Z数组。 2. 具体实现 以下面的这个对应关系为例&#xff0c;进行相应编程实现。 X [3.7,7.7,-6.6,1.5,-4.5…

用vue实现pdf预览

iframe <iframe :src"fileURLOther"></iframe> import axios from "axios"; data() {return {fileURLOther: "",url:,id:} }methods&#xff1a;{openPDF() {axios({method: "get",url: this.url,//文件的urlparams: {fi…

Linux系统编程学习 NO.9——git、gdb

前言 本篇文章简单介绍了Linux操作系统中两个实用的开发工具git版本控制器和gdb调试器。 git 什么是git&#xff1f; git是一款开源的分布式版本控制软件。它不仅具有网络功能&#xff0c;还是服务端与客户端一体的软件。它可以高效的处理程序项目中的版本管理。它是Linux内…

深入理解Linux网络笔记(六):深度理解TCP连接建立过程

本文为《深入理解Linux网络》学习笔记&#xff0c;使用的Linux源码版本是3.10&#xff0c;网卡驱动默认采用的都是Intel的igb网卡驱动 Linux源码在线阅读&#xff1a;https://elixir.bootlin.com/linux/v3.10/source 5、深度理解TCP连接建立过程 1&#xff09;、深入理解liste…

python查找算法_顺序查找

顺序查找&#xff08;Sequential Search&#xff09;是一种简单直观的搜索算法&#xff0c;用于在无序数组中查找特定元素。它的基本思想是逐个遍历数组中的元素&#xff0c;直到找到目标元素或遍历完整个数组。本文将介绍顺序查找的基本原理&#xff0c;并通过Python代码进行详…

网络爬虫|Selenium——find_element_by_xpath()的几种方法

Xpath (XML Path Language)&#xff0c;是W3C定义的用来在XML文档中选择节点的语言 一、从根目录/开始 有点像Linux的文件查看&#xff0c;/代表根目录&#xff0c;一级一级的查找&#xff0c;直接子节点&#xff0c;相当于css_selector中的>号 /html/body/div/p 二、根据…

LTspice学习笔记

参考博文 LTspice 软件仿真入门–LLC开环仿真练习LTspice:模拟变压器的简单步骤SPICE 语言基本语法和规则

hashMap索引原理

平日里面经常使用map这种数据结构&#xff0c;令人称奇的是他的访问速度为什么那么快&#xff1f;为什么可以通过key以接近O(1)的速度查找&#xff1f; 一、基础数据结构特点分析 1.1数组 查找的时间复杂度为O(1) 插入时间复杂度为O(n) 1.2链表 查找的时间复杂度为O(n) 插…

【Rust】6、练习:自己实现 ls

文章目录 一、CLI Utilities Rust 学完&#xff0c;想找些练手的项目&#xff0c;怎么办&#xff1f;可参考这个文章&#xff0c;列出的 15 个项目。 一、CLI Utilities github 参考 lsd 项目地址 cargo.toml [dependencies] clap "2"main.rs extern crate cl…

【剑指offer|图解|链表】链表的中间结点 + 链表中倒数第k个结点

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、算法模板 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️链表的中间结点二. ⛳️链表中倒数第k个结点&#x1f4dd;结语 &#x1f4c…

CUDA核函数,如何设置grid和block即不超过大小又能够遍历整个volume

此问题答案来自于openAI 1、Grid 大小&#xff1a; Grid 的大小由 dim3 grid 定义&#xff0c;其三个分量分别表示在 x、y、z 方向上的 Grid 数量。Grid 的大小不应该超过 GPU 的最大 Grid 大小。cudaDeviceGetAttribute获取限制。 int maxGridSizeX, maxGridSizeY, maxGridS…

最全Redis面试题整理

什么是Redis&#xff1f; Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的内存中数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构&#xff0c;包括字符串、哈希表、列表、集合、有序集合等&#xff0c;这使得它非…

如何为视频添加旁白,有哪些操作技巧?

简而言之&#xff0c;画外音是视频的旁白&#xff0c;在教程视频中添加旁白可以使视频更加有趣&#xff0c;并向观看者传达更多的信息。 如果您是视频制作人&#xff0c;想要为视频添加旁白&#xff0c;可阅读以下文章&#xff0c;可以帮助您更好地进行配音。 制作配音的技巧…

2216. 美化数组的最少删除数 --力扣 --JAVA

题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;如果满足下述条件&#xff0c;则认为数组 nums 是一个 美丽数组 &#xff1a; nums.length 为偶数对所有满足 i % 2 0 的下标 i &#xff0c;nums[i] ! nums[i 1] 均成立 注意&#xff0c;空数组同样认为是美丽数组。…