疫情防控交流社区平台——4.1 Redis一站式高性能存储(点赞功能)

🌕Redis一站式高性能存储(点赞功能)

一、点赞

在这里插入图片描述

把数据存到redis里,而存到redis里就好像我们操作一个map一样,非常简单。因此,数据访问层就不单独写了,因为太简单了,直接写业务层。在业务过程中,我们要需要存数据,直接调用redisTemplate往里存就行了,取也是同样的。
然后,在项目redis存数据取数据的操作数据过程中,是以key为关键的,是面向key去编程的,所以为了能让key反复复用,最好给redis写一个工具,专门用来生成它的key,方便复用。

1.1 RedisKeyUtil

package com.yty.community.util;

/*生成redis的key的工具类,方便复用*/
public class RedisKeyUtil {

    private static final String SPLIT = ":";
    private static final String PREFIX_ENTITY_LIKE = "like:entity";

    //1.生成某个实体的赞 这样一个key
    //实体就要传入实体的两个关键信息Type和Id
    //key:like:entity:entityType:entityId 对应的值--> set(userId)
    public static String getEntityLikeKey(int entityType,int entityId){
        return PREFIX_ENTITY_LIKE + SPLIT +entityType +SPLIT +entityId;
    }
}

1.2 LikeService

@Service
public class LikeService {

    //要把数据存到redis,所以注入redisTemplate
    @Autowired
    private RedisTemplate redisTemplate;

    //一、点赞
    public void like(int userId,int entityType,int entityId){
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);  //获得(声明)key
        //❤判断userId在不在里面(在就说明已经点赞了,不在,说明未点赞)
        Boolean isMember = redisTemplate.opsForSet().isMember(entityLikeKey, userId);
        if (isMember){
            redisTemplate.opsForSet().remove(entityLikeKey,userId);//如果在,点击的作用就是去取消喜欢,所以去除掉userId
        }else {
            redisTemplate.opsForSet().add(entityLikeKey,userId);//如果在,点击的作用就是去添加喜欢,所以去添加userId
        }
    }

    //二、查询某实体点赞数量(也就是被点赞数)
    public long findEntityLikeCount(int entityType,int entityId){
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);  //获得(声明)key
        return redisTemplate.opsForSet().size(entityLikeKey);
    }

    //三、查询某人对某实体的点赞状态(有没有点过赞)
    public int findEntityLikeStatus(int userId,int entityType,int entityId){
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);  //获得(声明)key
        return redisTemplate.opsForSet().isMember(entityLikeKey,userId) ? 1:0;
        //1 true点了赞  0 false没点赞
    }
}

1.3 LikeController

@Controller
public class LikeController {

    @Autowired
    private LikeService likeService;
    @Autowired
    private HostHolder hostHolder;

    @RequestMapping(path ="/like",method = RequestMethod.POST)
    @ResponseBody
    public String like(int entityType,int entityId){
        //获取当前用户 _ 不用判断登录状态,因为有拦截器,添加一下即可。后期security也可以的。
        User user = hostHolder.getUsers();

        //点赞
        likeService.like(user.getId(),entityType,entityId);

        //统计点赞数量
        long likeCount = likeService.findEntityLikeCount(entityType, entityId);
        //统计点赞状态
        int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId);
        //最终要把这两个值传给页面,封装一下再传
        //返回的结果
        Map<String,Object> map = new HashMap<>();
        map.put("likeCount",likeCount);
        map.put("likeStatus",likeStatus);

        return CommunityUtil.getJSONString(0,null,map);
    }
}
1.3.1 HomeController

这里加逻辑是为了让 首页每个帖子的赞的数量能实时显示,所以加一个逻辑上去

在这里插入图片描述

1.3.2 DiscussPostController

同样的,帖子详情页也要进行帖子点赞量的实时显示。所以也要添加逻辑
对帖子、评论、评论回复都要添加对应逻辑

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

1.4 页面测试

在这里插入图片描述
这里两个赞是我用了两个账号进行点赞的。
换第三个账号截图的。
在这里插入图片描述
然后我再给它点个赞,退出账号游客观看点赞数
在这里插入图片描述
成功!

1.5 Redis测试结果

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

二、我收到的赞

在这里插入图片描述

2.1 RedisKeyUtil

/*生成redis的key的工具类,方便复用*/
public class RedisKeyUtil {

    ...
    private static final String PREFIX_USER_LIKE = "like:user";

	...

    //2.某一个用户收到的赞
    //key:like:user:userId 对应的值--> int
    public static  String getUserLikeKey(int userId){
        return PREFIX_USER_LIKE + SPLIT + userId;
    }
}

2.2 LikeService

对“点赞”方法改一下,加一个维度计入那个数量,也就是一个业务当中会连续执行两次更新操作,所以整个业务要保证事务性。
那Redis怎么保证事务呢?编程式事务解决。所以将点赞方法内的代码进行重构

//一、点赞
    public void like(int userId,int entityType,int entityId,int entityUserId){
//        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);  //获得(声明)key
//        //❤判断userId在不在里面(在就说明已经点赞了,不在,说明未点赞)
//        Boolean isMember = redisTemplate.opsForSet().isMember(entityLikeKey, userId);
//        if (isMember){
//            redisTemplate.opsForSet().remove(entityLikeKey,userId);//如果在,点击的作用就是去取消喜欢,所以去除掉userId
//        }else {
//            redisTemplate.opsForSet().add(entityLikeKey,userId);//如果在,点击的作用就是去添加喜欢,所以去添加userId
//        }

        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);         //获得(声明)key
                String userLikeKey = RedisKeyUtil.getUserLikeKey(entityUserId);//获得(声明)key,entityUserId是被赞人的id,userId是点赞人的id

                boolean isMember = redisTemplate.opsForSet().isMember(entityLikeKey, userId); //查看当前用户有没有对实体点过赞
                //这里遵循了查询不放在事务中,要么在开始,要么在结束
                operations.multi();//开启事务
                if (isMember){//如果在,点击的作用就是去取消
                    operations.opsForSet().remove(entityLikeKey,userId);
                    operations.opsForValue().decrement(userLikeKey);     //点赞量-1
                }else {//如果不在,点击的作用就是去添加
                    operations.opsForSet().add(entityLikeKey,userId);
                    operations.opsForValue().increment(userLikeKey);   //点赞量+1
                }
                return operations.exec();//关闭事务
            }
        });
    }

	//查询某个用户获得的赞的数量
    public int findUserLikeCount(int userId){
        String userLikeKey = RedisKeyUtil.getUserLikeKey(userId);
        Integer count = (Integer) redisTemplate.opsForValue().get(userLikeKey);
        return count==null ? 0 : count.intValue();//如果count为空就返回0,否则就返回count的整数值
    }

2.3 LikeController

在这里插入图片描述

2.4 UserController

	//个人主页(不止查看当前用户的主页,更是任意人的主页,所以这里传过来用户id,就知道去谁的主页)
    @RequestMapping(path = "/profile/{userId}",method = RequestMethod.GET)
    public String getProfilePage(@PathVariable("userId")int userId,Model model){
        User user = userService.findByUserId(userId);
        if (user == null){
            throw new RuntimeException("该用户不存在!");
        }
        //用户
        model.addAttribute("user",user);
        //查点赞数量
        int likeCount = likeService.findUserLikeCount(userId);
        model.addAttribute("likeCount",likeCount);

        return "/site/profile";
    }

2.5 页面修改

profile.html

2.6 测试

在这里插入图片描述
这是因为重构了方法,所以之前的数据用不了了。我这里刷新一下,重新测试。
在这里插入图片描述
一看首页:
在这里插入图片描述
点赞数确实没了,然后点赞帖子,退出账号换一个账号查看:
在这里插入图片描述
数量为1,成功!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

11_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值