黑马Redis实战项目——黑马点评笔记05 | 达人探店

黑马Redis实战项目——黑马点评笔记05 | 达人探店

在这里插入图片描述
重点:

  1. 基于Redis中List的点赞列表
  2. 基于Redis中SortedSet的点赞排行榜

1、发布探店笔记

在这里插入图片描述
使用springboot框架整合mybatisplus实现


2、查看探店笔记

请求接口:
在这里插入图片描述在这里插入图片描述
一种实现方式是返回一个包含blog和user信息的Dto对象,但是过程繁琐。
因此简化为直接在Blog实体类,添加用户头像和用户名称两个属性,并加上mp提供的注解@TableField(exist = false) //当前属性不属于表中字段

//BlogController类中调用queryBlogById方法
	@GetMapping("/{id}")
    public Result queryBlogById(@PathVariable("id") Long id){
        return blogService.queryBlogById(id);
    }

//IBlogService接口中定义queryBlogById方法
public interface IBlogService extends IService<Blog> {

    Result queryHotBlog(Integer current);

    Result queryBlogById(Long id);
}

//BlogServiceImpl类中实现queryBlogById方法
	@Override
    public Result queryBlogById(Long id) {
        //1 查询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());
    }

3、点赞

请求接口:
在这里插入图片描述
在这里插入图片描述
代码实现:
1、给Blog对象增加isLike属性

	/**
     * 是否点赞过了
     */
    @TableField(exist = false)
    private Boolean isLike;

2、调用likeBlog方法

	//BlogController调用likeBlog方法
	@PutMapping("/like/{id}")
    public Result likeBlog(@PathVariable("id") Long id) {
        // 修改点赞数量
        return blogService.likeBlog(id);
    }
    
    //IBlogService接口声明likeBlog方法
    Result likeBlog(Long id);
    
	//BlogServiceImpl类实现likeBlog方法
	@Override
    public Result likeBlog(Long id) {
        //1 获取当前用户
        Long userId = UserHolder.getUser().getId();
        //2 判断当前用户是否已经点赞
        String key = "blog:liked:" + id;
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        if(BooleanUtil.isFalse(isMember)){
            //3 如果未点赞,可以点赞
            //3.1 数据库点赞数+1
            boolean isSucess = update().setSql("liked = liked + 1").eq("id", id).update();
            //3.2 保存用户到Redis的set集合
            if(isSucess){
                stringRedisTemplate.opsForSet().add(key, userId.toString());
            }
        }else{
            //4 如果已点赞
            //4.1 数据库点赞数-1
            boolean isSucess = update().setSql("liked = liked - 1").eq("id", id).update();
            //4.2 把用户从Redis的set集合移除
            stringRedisTemplate.opsForSet().remove(key, userId.toString());
        }
        return Result.ok();
    }

3、修改根据id查询博客的点赞业务

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) {
        //1 获取当前用户
        Long userId = UserHolder.getUser().getId();
        //2 判断当前用户是否已经点赞
        String key = "blog:liked:" + blog.getId();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        blog.setIsLike(BooleanUtil.isTrue(isMember));
    }

4、修改分页查询下的点赞业务

@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);
    }

4、点赞排行榜

在这里插入图片描述在这里插入图片描述因为set集合是无序的,但排行榜需要显示前5个点赞的用户,要想有序且不重复,只能用sortSet了。
这里用redis的sortSet来代替set,把之前的点赞功能,用户id存入set集合改为存入ZSet,使用sorce(key,value)方法来获取该键值的sorce,若没有则返回null,用来代替之前set的ismembet方法

代码实现:
1、修改点赞功能

    @Override
    public Result likeBlog(Long id) {
        //1 获取当前用户
        Long userId = UserHolder.getUser().getId();
        //2 判断当前用户是否已经点赞
        String key = "blog:liked:" + id;
//        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
//        if(BooleanUtil.isFalse(isMember)){
        if(score==null){
            //3 如果未点赞,可以点赞
            //3.1 数据库点赞数+1
            boolean isSucess = update().setSql("liked = liked + 1").eq("id", id).update();
            //3.2 保存用户到Redis的sorted_set集合 zadd key value score
            if(isSucess){
//                stringRedisTemplate.opsForSet().add(key, userId.toString());
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());
            }
        }else{
            //4 如果已点赞
            //4.1 数据库点赞数-1
            boolean isSucess = update().setSql("liked = liked - 1").eq("id", id).update();
            //4.2 把用户从Redis的set集合移除
//            stringRedisTemplate.opsForSet().remove(key, userId.toString());
            stringRedisTemplate.opsForZSet().remove(key, userId.toString());
        }
        return Result.ok();
    }

2、修改查询(根据id查,查询详情)

    private void isBlogLiked(Blog blog) {
        //1 获取当前用户
        UserDTO user = UserHolder.getUser();
        if(user==null){
            //用户未登录,无需查询是否点赞
            return;
        }
        Long userId = user.getId();
        //2 判断当前用户是否已经点赞
        String key = "blog:liked:" + blog.getId();
//        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
//        blog.setIsLike(BooleanUtil.isTrue(isMember));
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        blog.setIsLike(score!=null);
    }

3、点赞列表查询

//BlogController类调用queryBlogLikes方法
	@GetMapping("/likes/{id}")
    public Result queryBlogLikes(@PathVariable("id") Long id){
        return blogService.queryBlogLikes(id);
    }

//IBlogService接口声明queryBlogLikes方法
Result queryBlogLikes(Long id);

//BlogServiceImpl类实现queryBlogLikes方法
@Override
    public Result queryBlogLikes(Long id) {
        //1 查询top5的点赞用户 zrange key 0 4
        String key = BLOG_LIKED_KEY + id;
        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)
        List<UserDTO> userDTOS = userService.query()
                .in("id", ids).last("ORDER BY FIELD (id, " + idStr + ")").list()
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
//        List<UserDTO> userDTOS = userService.listByIds(ids).stream()
//                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
//                .collect(Collectors.toList());
        //4 返回
        return Result.ok(userDTOS);
    }

注意: queryBlogLikes方法中sql语句的 list.in(…, …)查询出来的是后点赞的在前,先点赞的在后,需要我们自定义sql查询,用last最后一条sql语句,手写order by的sql。


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值