文章目录
- 发布探店笔记
- 查看探店笔记
- 点赞功能
- 点赞排行榜功能
发布探店笔记
这个其实比较简单,就是把笔记保存到数据库tb_blog中去
@PostMapping
public Result saveBlog(@RequestBody Blog blog) {
// 获取登录用户
UserDTO user = UserHolder.getUser();
blog.setUserId(user.getId());
// 保存探店博文
blogService.save(blog);
// 返回id
return Result.ok(blog.getId());
}
查看探店笔记
这个就是查询数据库中的笔记
分查询我的笔记和查询热门笔记(主页展示使用)以及根据id查询
@GetMapping("/of/me")
public Result queryMyBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
// 获取登录用户
UserDTO user = UserHolder.getUser();
// 根据用户查询
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);
}
@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 ->{
this.queryBlogUser(blog);
this.isBlogLiked(blog);
});
return Result.ok(records);
}
@Override
public Result queryBlogById(Long id) {
// 1. 查询blog
Blog blog = getById(id);
if(blog == null){
return Result.fail("笔记不存在!");
}
// 2. 查询blog有关的用户
queryBlogUser(blog);
// 3. 查询blog是否被点赞了
isBlogLiked(blog);
return Result.ok(blog);
}
private void isBlogLiked(Blog blog) {
UserDTO user = UserHolder.getUser();
if(user == null){
// 用户未登录,无需查询是否点赞
return;
}
// 1. 获取当前用户
Long userId = user.getId();
// 2. 判断当前登录的用户是否已经点赞
String key = RedisConstants.BLOG_LIKED_KEY + blog.getId();
Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
blog.setIsLike(score != null);
}
private void queryBlogUser(Blog blog) {
Long userId = blog.getUserId();
User user = userService.getById(userId);
blog.setName(user.getNickName());
blog.setIcon(user.getIcon());
}
点赞功能
点赞我们要防止刷赞,只能让一个用户点一个赞,所以我们不能只是简单的保存到数据库中,我们可以使用Redis的set结构把我们当前博客的点赞用户保存起来,可以保证唯一性,但是,我们下面要做关于点赞排行榜的功能,在点赞排行榜中,我们会根据点赞的先后顺序排序,使用set就不行了,我们就不在使用set结构了,我们改为SortedSet结构,代码见下小节。
点赞排行榜功能
我们使用SortedSet数据结构来存储点赞的用户,从redsi中查询top5的点赞用户 zrange key 0 4
然后根据用户id去查询用户,把查到的User转换成UserDto返回给前端
@Override
public Result likeBlog(Long id) {
// 1. 获取当前用户
Long userId = UserHolder.getUser().getId();
// 2. 判断当前登录的用户是否已经点赞
String key = RedisConstants.BLOG_LIKED_KEY + id;
Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
if(score == null){
// 3. 如果未点赞,可以点赞
// 3.1 数据库点赞数+1,
boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
// 3.2 保护用户到Redis的Sortedset集合 zadd key value score
if(isSuccess){
stringRedisTemplate.opsForZSet().add(key, userId.toString(),System.currentTimeMillis());
}
}else{
// 4. 如果已点赞,取消点赞
// 4.1 数据库点赞数-1
boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update();
// 4.2 把用户从Redis的set集合移除
if(isSuccess){
stringRedisTemplate.opsForZSet().remove(key, userId.toString());
}
}
return Result.ok();
}
@Override
public Result queryBlogLikes(Long id) {
String key = RedisConstants.BLOG_LIKED_KEY + id;
// 查询top5的点赞用户 zrange key 0 4
Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
if(top5 == null || top5.isEmpty()){
return Result.ok(Collections.emptyList());
}
// 2. 解析出其中的用户id
List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
String idStr = StrUtil.join(",", ids);
// 3. 根据用户id查询用户 where id in(5,1) order by field(id, 5,1) 如果不指定排序数据库会默认按照id排序,那就不是我们想要的查询顺序,那就要给数据库指定排序
// 使用order by field(字段,排序的顺序); 我们使用字符串拼接进去id的序列
List<User> users = userService.query()
.in("id", ids)
.last("ORDER BY FIELD(id," + idStr + ")").list();
List<UserDTO> userDTOS = users.stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class))
.collect(Collectors.toList());
// 4. 返回
return Result.ok(userDTOS);
}