Redis中BitMap实现签到与统计连续签到功能

服务层代码
//签到
    @Override
    public Result sign() {
        //1.获取当前登录的用户
        Long userId = UserHolder.getUser().getId();
        //获取日期
        LocalDateTime now = LocalDateTime.now();
        //拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + keySuffix;
        //获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //写入Redis SETBIT key offset 1
        stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
        return Result.ok();
    }
    //统计连续签到
    @Override
    public Result signCount() {
        //1.获取当前登录的用户
        Long userId = UserHolder.getUser().getId();
        //获取日期
        LocalDateTime now = LocalDateTime.now();
        //拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + keySuffix;
        //获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //获取本月截止今天为止的所有签到记录,返回的是一个十进制的数字  BITFIELD sign:5:202409 GET u14 0  14为要查多少位即当月为几号  0为从1号开始查
        List<Long> result = stringRedisTemplate.opsForValue().bitField(
                key,
                BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
        );
        if (result == null || result.isEmpty()){
            //没有任何签到结果
            return Result.ok(0);
        }
        Long num = result.get(0);
        if(num == null || num == 0){
            return Result.ok(0);
        }
        //循环遍历
        int count = 0;
        while(true){
            //让这个数据与1作与运算,得到数字的最后一个bit位   判断这个bit位是否为0
            if((num & 1) == 0){
                //如果为0,说明未签到,结束
                break;
            } else {
                //如果为1,说明已签到,计数器加1
                count++;
            }
            num >>>= 1;
        }
        return Result.ok(count);
    }

在SpringBoot项目中,使用RedisBitMap数据结构可以有效地实现用户的签到签到统计功能RedisBitMap是一种特殊的数据类型,它通过一个二进制位数组来存储数据,可以将每一位看作一个开关,用来表示一个布尔值。这种方法在处理连续日期或者大规模数据时,可以极大程度地节省空间。 ### 实现步骤如下: 1. **引入依赖**:首先确保你的SpringBoot项目中已经引入了Spring Data Redis的依赖。 2. **配置Redis连接**:在`application.properties`或`application.yml`文件中配置Redis的连接信息。 3. **签到功能**: - 使用用户的唯一标识(例如用户ID)来作为BitMap的key。 - 使用日期(通常是年月日,可以转换为一个整数)作为offset,这个offset就是BitMap中的位置。 - 使用`SETBIT`命令将对应日期的offset设置为1,表示用户当天签到。 4. **签到统计功能**: - 使用`GETBIT`命令可以检查用户在特定日期是否签到,返回1表示签到,返回0表示未签到。 - 使用`BITCOUNT`命令可以统计某个用户在一定时间范围内的签到天数。 - 使用`BITOP`命令可以实现复杂的逻辑操作,比如统计连续签到天数。 5. **接口实现**: - 在SpringBoot中创建相应的Controller来处理签到请求。 - 在Service层调用RedisTemplate操作BitMap进行签到统计。 - 在Repository层定义Redis操作的方法。 ### 示例代码片段: ```java // Controller @RestController @RequestMapping("/api/signin") public class SignInController { @Autowired private SignInService signInService; @PostMapping("/checkin") public ResponseEntity<?> userCheckIn(@RequestParam Long userId) { signInService.userCheckIn(userId); return ResponseEntity.ok("Sign in successful."); } // 其他方法... } // Service @Service public class SignInService { @Autowired private StringRedisTemplate stringRedisTemplate; public void userCheckIn(Long userId) { LocalDate today = LocalDate.now(); String key = "signin:" + userId; int offset = today.toEpochDay(); stringRedisTemplate.opsForValue().setBit(key, offset, true); } // 其他方法... } ``` ### 注意事项: - 在使用BitMap时需要注意offset的有效范围,通常应该在一个合理的日期范围内,否则可能会有数据错位的风险。 - BitMap中每个位只能表示0或1两种状态,因此在设计时需要确定好这两种状态的意义。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值