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 {
@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对象中的userId
去tb_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);
}