項目架構,這是作為demo展示使用:
Redis config:
package com.zy.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** @Author: zy* @Date: 2025-03-08-13:22* @Description:*/
@Configuration
public class RedisConfig {/*** RedisTemplate配置*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();template.setConnectionFactory(factory);Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// key采用String的序列化方式template.setKeySerializer(stringRedisSerializer);// hash的key也采用String的序列化方式template.setHashKeySerializer(stringRedisSerializer);// value序列化方式采用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}
}
Controller:
package com.zy.controller;import com.zy.config.RedisConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.Optional;/*** @Author: zy* @Date: 2025-03-08-12:43* @Description:*/
@RestController
@Slf4j
@RequestMapping("/user")
public class SignController {@Autowiredprivate RedisTemplate redisTemplate;@PostMapping("/sign")public Boolean sign() {try {//1. 獲取登錄用戶//Long userId = SSOThreadHolder.getUserAndCheck().getUserId();Long userId = 1001012345L;//2. 獲取日期LocalDateTime now = LocalDateTime.now();for (int i = 0; i < 100; i++) {LocalDate date = LocalDateTime.now().minusDays(i).toLocalDate();String format = date.format(DateTimeFormatter.ofPattern(":yyyyMM"));//3. 拼接keyString keySuffix = format;String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;log.info("redis key:" + key);//4. 獲取今天是本月的第幾天int dayOfMonth = date.getDayOfMonth();//5. 寫入redis setbit key offset 1System.out.println("dayOfMonth:" + dayOfMonth);Boolean aBoolean = redisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);System.out.println("aboolean:" + aBoolean);}} catch (Exception e) {e.printStackTrace();log.error(e.getMessage());}return true;}@GetMapping("/signCount")public String signCount() {long l = countSignInDays("sign:1001012345:202503");System.out.println("l:" + l);return String.valueOf(l);}/*** 統計當前月的簽到總數** @param key Redis鍵* @return 簽到總數*/public long countSignInDays(String key) {key = "sign:1001012345:202503";// 獲取當前月的總天數YearMonth currentYearMonth = YearMonth.now();int daysInMonth = currentYearMonth.lengthOfMonth();// 使用 execute 方法執行 BITCOUNT 命令String finalKey = key;Long bitCount = (Long) redisTemplate.execute((RedisConnection connection) -> {// 檢查鍵是否存在if (!connection.exists(finalKey.getBytes())) {return 0L;}// 執行 BITCOUNT 命令,統計指定范圍內的 1 的數量return connection.bitCount(finalKey.getBytes(), 0, daysInMonth - 1);});return Optional.ofNullable(bitCount).orElse(0L);}}
yml文件:
server:port: 8090spring:#redis哨兵配置redis:sentinel:master: mymasternodes: # 我這里使用的是哨兵模式,不影響,根據你自己的來,但是如果沒有,為啥不搭建一下,自己使用呢- localhost:26379- localhost:26380- localhost:26381password: 你的密碼password: 你的密碼
接口測試:
簽到接口,在代碼中模擬了100天的簽到
統計接口:統計的什么,具體看代碼