Redis框架(十四):大众点评项目 基于Redis实现点赞功能实现

大众点评项目 基于Redis的点赞功能实现

SpringCloud章节复习已经过去,新的章节Redis开始了,这个章节中将会回顾Redis实战项目 大众点评
主要依照以下几个原则

  1. 基础+实战的Demo和Coding上传到我的代码仓库
  2. 在原有基础上加入一些设计模式,stream+lamdba等新的糖
  3. 通过DeBug调试,进入组件源码去分析底层运行的规则和设计模式

代码会同步在我的gitee中去,觉得不错的同学记得一键三连求关注,感谢:
Redis优化-链接: RedisFunctionLikeProject

需求:基于Redis实现点赞功能实现

** 点赞功能的基本实现, 点赞用户排序, 相关用户信息显示**

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

业务实战

  1. 在原有Blog类的基础上添加相关字段
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_blog")
public class Blog implements Serializable {
    /**
     * 用户图标
     */
    @TableField(exist = false)
    private String icon;
    /**
     * 用户姓名
     */
    @TableField(exist = false)
    private String name;
    /**
     * 是否点赞过了
     */
    @TableField(exist = false)
    private Boolean isLike;
 }

**@TableField(exist = false)**表示不存在,我们通过在业务层手动注入这些信息

在这里插入图片描述

  1. 通过相应的url进行基本操作,业务放到Service层去做

在这里插入图片描述

原有业务

    @PutMapping("/like/{id}")
    public Result likeBlog(@PathVariable("id") Long id) {
        // 修改点赞数量
        return blogService.likeBlog(id);
        blogService.update()
                .setSql("liked = liked + 1").eq("id", id).update();
        return Result.ok();
    }

这里对点赞次数没有限制,是不行的,我们希望对点赞功能只能一次;

    @PutMapping("/like/{id}")
    public Result likeBlog(@PathVariable("id") Long id) {
        // 修改点赞数量
        return blogService.likeBlog(id);

    }

  1. 将点赞信息存放到Redis中,存放类型是zset类型,通过这种类型,可以保证
  • 数据唯一性
  • 指定SCORE属性进行排序,我们选用时间戳System.currentTimeMillis()
    /**
     * @Function:点赞功能实现
     * @param id
     * @return
     */
    @Override
    public Result likeBlog(Long id) {
        Long userId = UserHolder.getUser().getId();
        //判断当前用户是否点赞
        String key = RedisConstants.BLOG_LIKED_KEY + id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());

//        if (!member) {  包装类可能为null
//        if (BooleanUtil.isFalse(member)) {
        if (score == null) {
            //如果set中不存在,说明没有
//            blog.setIsLike(false);
            boolean flag = update().setSql("liked = liked + 1").eq("id", id).update();
            if (flag) {
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());
            }

        }else{
            //如果没有点赞
//            blog.setIsLike(true);
            boolean flag = update().setSql("liked = liked - 1").eq("id", id).update();
            if (flag) {
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            }
        }

        return Result.ok();
    }
  1. 点赞排序,显示用户信息

在这里插入图片描述

    @GetMapping("/likes/{id}")
    public Result likesBlog(@PathVariable("id") Long id) {
        // 修改点赞数量
        return blogService.queryBlogLikes(id);
    }
    @Override
    public Result queryBlogLikes(Long id) {

        String key = RedisConstants.BLOG_LIKED_KEY + id;
        Set<String> topFive = stringRedisTemplate.opsForZSet().range(key, 0, 4);

        if (topFive == null || topFive.isEmpty()) {
            return Result.ok(Collections.emptyList());
        }

        List<Long> userIdOrder = topFive.stream().map(Long::valueOf).collect(Collectors.toList());
        String idStr = StrUtil.join(",", userIdOrder);

        List<UserDTO> userDTOS = userService.query()
                .in("id", userIdOrder)
                .last("ORDER BY FIELD(id, "+ idStr +  ")").list()
                .stream()
                .map(user -> {
            return BeanUtil.copyProperties(user, UserDTO.class);
        }).collect(Collectors.toList());



        return Result.ok(userDTOS);
    }

这里需要注意下 userService.query() .in("id", userIdOrder) .last("ORDER BY FIELD(id, "+ idStr + ")").list()
这个是为了按时间顺序展示来进行的,ORDER BY FIELD就是值其排序方式按我们的要求来进行,这里通过MP的last方法进行了拼装

总体代码展示

@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {

    @Resource
    private IBlogService blogService;

    @Resource
    private IUserService userService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    /**
     * @Function:点赞功能实现
     * @param id
     * @return
     */
    @Override
    public Result likeBlog(Long id) {
        Long userId = UserHolder.getUser().getId();
        //判断当前用户是否点赞
        String key = RedisConstants.BLOG_LIKED_KEY + id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());

//        if (!member) {  包装类可能为null
//        if (BooleanUtil.isFalse(member)) {
        if (score == null) {
            //如果set中不存在,说明没有
//            blog.setIsLike(false);
            boolean flag = update().setSql("liked = liked + 1").eq("id", id).update();
            if (flag) {
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());
            }

        }else{
            //如果没有点赞
//            blog.setIsLike(true);
            boolean flag = update().setSql("liked = liked - 1").eq("id", id).update();
            if (flag) {
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            }
        }

        return Result.ok();
    }

    @Override
    public Result queryBlogLikes(Long id) {

        String key = RedisConstants.BLOG_LIKED_KEY + id;
        Set<String> topFive = stringRedisTemplate.opsForZSet().range(key, 0, 4);

        if (topFive == null || topFive.isEmpty()) {
            return Result.ok(Collections.emptyList());
        }

        List<Long> userIdOrder = topFive.stream().map(Long::valueOf).collect(Collectors.toList());
        String idStr = StrUtil.join(",", userIdOrder);

        List<UserDTO> userDTOS = userService.query()
                .in("id", userIdOrder)
                .last("ORDER BY FIELD(id, "+ idStr +  ")").list()
                .stream()
                .map(user -> {
            return BeanUtil.copyProperties(user, UserDTO.class);
        }).collect(Collectors.toList());



        return Result.ok(userDTOS);
    }




总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值