我们在很多app中会看到签到这个功能。但是这个功能是怎么做的呢?我们接下来就说下。
网上说的比较多的是:java签到功能_使用RedisTemplate操作bitmap完成每日签到_weixin_39765695的博客-CSDN博客
但是很不全面。接下来我们就说下。可实战使用。
技术选型
mysql 把签到记录存储到数据库中。好处:开发简单。坏处:当数据量大时,存储到mysql就不合适了。
redis 将签到信息存储的redis中。(我们以此为标准)
实现
引入相应的jar包。我们在springBoot中开发。
<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
Redis的配置类
/**
* Redis配置类
*/
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableCaching
public class RedisInitializer extends CachingConfigurerSupport {
@Autowired
LettuceConnectionFactory redisConnectionFactory;
@Bean
public RedisTemplate<Object, Object> redisTemplate() {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
// value值的序列化采用GenericJackson2JsonRedisSerializer
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
// 开启事务特性
//template.setEnableTransactionSupport(true);
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
RedisUtil 这个是Redis的工具类
/**
* Redis工具类
*
*/
@Component
@DependsOn({"redisInitializer"})
public class RedisUtil {
private static Logger log = LoggerFactory.getLogger(RedisUtil.class);
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
/**
* 签到
*
* @param key
* @param offset
* @return
*/
public boolean setBit(String key, int offset) {
return redisTemplate.opsForValue().setBit(key, offset, true);
}
/**
* 查询是否签单
*
* @param key
* @param offset
* @return
*/
public boolean getBit(String key, int offset) {
return redisTemplate.opsForValue().getBit(key, offset);
}
/**
* 签到次数
*
* @param cacheKey
* @return
*/
public long getSignCount(String cacheKey) {
Long bitCount = (Long) redisTemplate.execute((RedisCallback) cbk -> cbk.bitCount(cacheKey.getBytes()));
return bitCount;
}
/**
* 获取连续签到次数
*
* @param cacheKey
* @param count
* @return
*/
public long getContinuousSignCount(String cacheKey, int count) {
long signCount = 0;
List<Long> list = redisTemplate.opsForValue().bitField(cacheKey, BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType
.unsigned(count)).valueAt(1));
if (list != null && list.size() > 0) {
long valueDec = list.get(0) != null ? list.get(0) : 0;
// System.out.println("valueDec..." + valueDec);
for (int i = 0; i < count; i++) {
if (valueDec >> 1 << 1 == valueDec) {
if (i > 1) {
break;
}