当前位置: 首页 > news >正文

Springboot redis bitMap实现用户签到以及统计,保姆级教程

项目架构,这是作为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配置
     */
    @Bean
    public 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序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.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 {

    @Autowired
    private 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. 拼接key
                String 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 1
                System.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: 8090


spring:
  #redis哨兵配置
  redis:
    sentinel:
      master: mymaster
      nodes: # 我这里使用的是哨兵模式,不影响,根据你自己的来,但是如果没有,为啥不搭建一下,自己使用呢
        - localhost:26379
        - localhost:26380
        - localhost:26381
      password: 你的密码
    password: 你的密码



接口测试:
签到接口,在代码中模拟了100天的签到
在这里插入图片描述

统计接口:统计的什么,具体看代码
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dtcms.com/a/58518.html

相关文章:

  • SpringBoot全栈开发:从数据库到Markdown文件导出的终极实践指南
  • TCP协议与包头格式
  • 计算机视觉中的前向卷绕算法全解析
  • 从0到1入门RabbitMQ
  • 完整例子和调用关系qt OpenGL
  • 线上接口tp99突然升高如何排查?
  • Python Flask 渲染静态程动态页面
  • PerceptronLexicalAnalyzer浅讲
  • 鬼泣:移动系统2
  • 技术债务未纳入计划管理怎么办
  • 在Dify中访问Gemini等模型代理设置指南
  • 蓝桥杯备考:离散化详解
  • kafka + flink +mysql 案例
  • [Web]get请求和post请求
  • 机器学校的考试风波:误差分析、过拟合和欠拟合
  • Java多线程和锁_八股场景题
  • 2025年人工智能的发展前景将呈现多维度、深层次的变革,涵盖技术突破、行业应用、算力基础设施、政策法规等多个领域.结合工作情况,个人看法参考。
  • Cocos Creator Shader入门实战(三):CCEffect参数配置讲解
  • 捌拾贰- 贝尔不等式 (2)
  • 大白话JavaScript闭包实现原理与在实际开发中的应用场景
  • AF3 correct_msa_restypes函数解读
  • mac本地代理nginx,解决跨域问题
  • 【Java代码审计 | 第六篇】XSS防范
  • 【React】React + Tailwind CSS 快速入门指南
  • VBA高级应用30例Excel中ListObject对象:提取表内单元格的格式元素
  • WPF 之SizeToContent
  • 8.1linux竞争与并发知识讲解(尽可能详细)_csdn
  • pta L1-003 个位数统计
  • LeetCode 738. 单调递增的数字 java题解
  • 2.装饰器模式