@Override public void sign() { // 通过redis存储签到信息 // key : sign:年月:用户id String yearAndMonth = DateUtils.formatDate(new Date(), "yyyyMM"); // Integer uid = TokenUtils.getUidFromToken(); // 通过ThreadLocal获取用户id Integer uid = UserUtils.getUid(); String signKey = String.format(RedisKeyEnum.KEY_SIGN.getKey(), yearAndMonth, uid); // offset是从0开始,本例中从1开始记录,offset是1表示1号,依次类推 Long day = Long.valueOf(LocalDate.now().getDayOfMonth()); boolean ret = RedisUtils.getBit(signKey, day); if (ret) { throw new RuntimeException("今日已签到"); } RedisUtils.setBit(signKey, day); // 签到成功送积分 // 从积分规则表中查询签到送多少积分, // PointRule pointRule = pointRuleService.ruleInfoByType(PointTypeEnum.TYPE_SIGN.getType()); // 使用redis缓存规则数据后的逻辑 List<PointRule> pointRules = pointRuleService.ruleList(); PointRule pointRule = pointRules.stream() .filter(item -> item.getPointType().equals(PointTypeEnum.TYPE_SIGN.getType())) .findFirst() .orElse(null); threadPoolExecutor.execute(() -> { PointInfo info = new PointInfo(); info.setUid(uid); info.setPoint(pointRule.getPoint()); info.setPointType(PointTypeEnum.TYPE_SIGN.getType()); // 然后向积分记录表中添加数据 try { pointInfoService.addPointInfo(info); } catch (Exception e) { // e.printStackTrace(); PointRetry retry = new PointRetry(); retry.setUid(uid); retry.setPoint(pointRule.getPoint()); retry.setPointType(PointTypeEnum.TYPE_SIGN.getType()); pointRetryService.addRetry(retry); } }); // 进行连续签到判断 // 使用bitfield命令获取指定范围的二进制数据,内部转为long类型数据返回 Long v = RedisUtils.bitfield(signKey, day.intValue(), 1); // 计算连续签到的天数,(方案:1将数据转为二进制字符串,2位运算) String s = Long.toBinaryString(v); int continueDay = 0; for (int i = s.length() - 1; i >= 0; i--) { char c = s.charAt(i); if (c == '1') { continueDay++; continue; } break; } // 根据连续签到天数额外送积分 PointRule pointRule2 = pointRuleService.ruleInfoByType(PointTypeEnum.TYPE_CONTINUE_SIGN.getType()); String days = pointRule2.getDays(); // 将json字符串转为列表对象 // 第二个参数:列表中元素的类型 List<ContinueDayInfo> continueDayInfos = JSON.parseArray(days, ContinueDayInfo.class); int finalContinueDay = continueDay; // 借助stream流来查找数据 ContinueDayInfo dayInfo = continueDayInfos.stream() .filter(item -> item.getDays().equals(finalContinueDay)) .findFirst() .orElse(null); // 如果找到对应的连续签到天数的数据,赠送积分 if (dayInfo != null) { PointInfo info2 = new PointInfo(); info2.setUid(uid); info2.setPoint(dayInfo.getPoint()); info2.setPointType(PointTypeEnum.TYPE_CONTINUE_SIGN.getType()); // 然后向积分记录表中添加数据 pointInfoService.addPointInfo(info2); } // for (ContinueDayInfo dayInfo : continueDayInfos) { // if (dayInfo.getDays().equals(continueDay)) { // // 送积分 // break; // } // } }