08.利用Redis实现签到功能

学习目标:

来源:黑马教程
使用Redis中BitMap数据结构使用签到功能和连续签到功能


学习产出:

请添加图片描述

解决方案:

1. 准备pom环境

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope><version>5.1.47</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><!--hutool--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.17</version></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.23.1</version></dependency>

2. 配置ThreadLocal和过滤器

public class UserHolder {private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();public static void saveUser(UserDTO user){tl.set(user);}public static UserDTO getUser(){return tl.get();}public static void removeUser(){tl.remove();}
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {@Autowiredprivate StringRedisTemplate redis;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/user/code","/user/login","/blog/hot","/shop/**","/shop-type/**","/voucher/**").order(2);registry.addInterceptor(new RefreshTokenInterceptor(redis)).addPathPatterns("/**").order(1);}
}
---------------------------------------------
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {//controller执行之前@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.判断是否需要拦截ThreadLocalif (UserHolder.getUser()==null) {response.setStatus(401);return false;}//7.放行return true;}//渲染后返回给前台数据前@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//移除用户,避免内存泄露UserHolder.removeUser();}
}
---------------------------------------------------
@Slf4j
public class RefreshTokenInterceptor implements HandlerInterceptor {//这个对象不是由spring管理的所以不能用注解自动注入private StringRedisTemplate redis;public RefreshTokenInterceptor(StringRedisTemplate redis) {this.redis = redis;}//controller执行之前@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取请求头中的tokenString token = request.getHeader("authorization");if (StrUtil.isBlank(token)) {return true;}//2.基于token获取redis中的用户//通过key取到hash中的map集合数据Map<Object, Object> userMap = redis.opsForHash().entries("login:token:" + token);//3.判断用户是否存在if (userMap.isEmpty()) {return true;}//5.将查询到的hash数据转为userDto对象UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);//6.存在,保存用户信息到ThreadLocal中UserHolder.saveUser(userDTO);//7.刷新token有效期redis.expire(LOGIN_USER_KEY + token, 30, TimeUnit.MINUTES);log.info("我是第一个拦截器当前拦截所有请求的用户为,线程为{},{}",UserHolder.getUser(),Thread.currentThread());//8.放行return true;}

3. Controller层:负责接收请求和向下分配

@RestController
@RequestMapping("/user")
public class UserController{@Resourceprivate IUserService userService;@PostMapping("/sign")public Result sign(){return userService.sign();}
}

4. Service层:负责业务的处理逻辑签到功能

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {private static final ObjectMapper mapper = new ObjectMapper();@Resourceprivate StringRedisTemplate redis;@Overridepublic Result sign() {//1. 获取当前登录用户IdLong userId = UserHolder.getUser().getId();//2.获取日期:Redis中的offset偏移量是从0开始算,偏移量n代表的这个月的第n+1天int offset = LocalDateTime.now().getDayOfMonth() - 1;//3.拼接key存入RedisLocalDateTime now = LocalDateTime.now();String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));String key = "sign:" + userId + keySuffix;//true代表的是存入BitMap中的二进制是1redis.opsForValue().setBit(key, offset, true);return Result.ok();}
}`5. Service层实现连续签到功能`
```java
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {private static final ObjectMapper mapper = new ObjectMapper();@Resourceprivate StringRedisTemplate redis;@Overridepublic Result signCount() {//1.获取当前登录用户Long userId = UserHolder.getUser().getId();//2.获取日期LocalDateTime nowTime = LocalDateTime.now();//3.拼接keyString keySuffix = nowTime.format(DateTimeFormatter.ofPattern(":yyyyMM"));String key = "sign:" + userId + keySuffix;//4.获取今天是第几天int day = nowTime.getDayOfMonth();//5.获取本月截至今天为止所有的签到记录,返回的是一个十进制数字List<Long> result = redis.opsForValue().bitField(key,BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(day)).valueAt(0));if (result.isEmpty() || result == null) {return Result.ok(0);}Long signCount = result.get(0);if (signCount == null || signCount == 0) {return Result.ok(0);}//6.遍历int count=0;while (true) {if ((signCount & 1) == 0) {//不为0,跳出循环break;} else {count++;signCount = signCount >> 1;}}//7.签到记录返回的十进制数字与1做 与运算return Result.ok(count);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

push github

一、生成密钥 打开git bash执行下面指令&#xff0c;Enter下一步Enter下一步..生成ssh key 密钥&#xff1b; ssh-keygen -t rsa 二、 复制公共密钥到git hub 登录github&#xff0c;在选项setting >> SSH and GPG key >> add new ssh添加刚才的公钥地址即可 验证…

Hadoop入门机安装hadoop

0目录 1.Hadoop入门 2.linux安装hadoop 1.Hadoop入门 定义 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下&#xff0c;开发分布式程序。充分利用集群的威力进行高速运算和存储。 优势 高可靠性&#xff1a;Hadoop底层维护多…

机器学习中XGBoost算法调参技巧

本文将详细解释XGBoost中十个最常用超参数的介绍&#xff0c;功能和值范围&#xff0c;及如何使用Optuna进行超参数调优。 对于XGBoost来说&#xff0c;默认的超参数是可以正常运行的&#xff0c;但是如果你想获得最佳的效果&#xff0c;那么就需要自行调整一些超参数来匹配你…

docker实践作业

1.安装docker服务&#xff0c;配置镜像加速器 2.下载系统镜像&#xff08;Ubuntu、 centos&#xff09; 3.基于下载的镜像创建两个容器 &#xff08;容器名一个为自己名字全拼&#xff0c;一个为首名字字母&#xff09; 4.容器的启动、 停止及重启操作 5.怎么查看正在运行的容器…

c++都补了c语言哪些坑?

目录 1.命名空间 1.1 定义 1.2 使用 2.缺省参数 2.1 概念 2.2 分类 3.函数重载 4.引用 4.1 概念 4.2 特性 4.3 常引用 4.4 引用和指针的区别 5.内联函数 1.命名空间 在 C/C 中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将…

AR地图微信小程序:数字化时代下地图应用的新突破

随着数字化时代的到来&#xff0c;地图应用成为人们日常生活中不可或缺的工具。而随着增强现实&#xff08;AR&#xff09;技术的快速发展&#xff0c;AR地图微信小程序应运而生&#xff0c;为用户提供了一种全新的地图导航体验。本文将深入探讨AR地图微信小程序的专业性和思考…

安卓系列机型-禁止卸载某个APP 防止误卸载软件 无需root权限

安卓系列机型-禁止安装某软件 防止“沉迷游戏的小孩”操作解析_安卓机器的博客-CSDN博客 上一期讲了如何禁止安装某个app。今天讲下如何禁止卸载某app。正好相反的操作。任何操作有利有弊。主要看使用者如何对待使用。 &#x1f494;&#x1f494;&#x1f494;以腾讯的一款游…

Android Lottie加载gson文件动画

一&#xff1a;Lottie的使用 在你工程的build.gradle文件里添加如下配置 implementation com.airbnb.android:lottie:3.4.0二&#xff1a;布局文件直接引入LottieAnimationView <com.airbnb.lottie.LottieAnimationViewandroid:id"id/lottie_view"android:layout…

2023年国赛 高教社杯数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…

基于Jenkins自动打包并部署docker环境

目录 1、安装docker-ce 2、阿里云镜像加速器 3、构建tomcat 基础镜像 4、构建一个Maven项目 实验环境 操作系统 IP地址 主机名 角色 CentOS7.5 192.168.200.111 git git服务器 CentOS7.5 192.168.200.112 Jenkins git客户端 jenkins服务器 CentOS7.5 192.168…

【实训项目】易行APP设计(c2c二手交易平台)

1.设计摘要 1.1市场背景 随着经济的迅速发展与科技日新月异的进步&#xff0c;家庭内的各项物品更新换代频率越来越快&#xff0c;人们购买新商品后越来越多旧的商品积压需要处理&#xff1b;在互联网电商的各种营销刺激下&#xff0c;消费者非常容易形成“冲动”消费&#x…

回归预测 | MATLAB实现DBN-ELM深度置信网络结合极限学习机多输入单输出回归预测

回归预测 | MATLAB实现DBN-ELM深度置信网络结合极限学习机多输入单输出回归预测 目录 回归预测 | MATLAB实现DBN-ELM深度置信网络结合极限学习机多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现DBN-ELM深度置信网络结合极限学习…

基于paddleocr的文档识别

1、版面分析 使用轻量模型PP-PicoDet检测模型实现版面各种类别的检测。 数据集&#xff1a; 英文&#xff1a;publaynet数据集的训练集合中包含35万张图像&#xff0c;验证集合中包含1.1万张图像。总共包含5个类别。 中文&#xff1a;CDLA据集的训练集合中包含5000张图像&a…

蓝蓝设计-UI设计公司作品-博晖创新原子吸收光谱仪软件交互及界面设计

博晖创新原子吸收光谱仪软件交互及界面设计 图标设计 | 交互设计 | 界面设计 博晖公司拥有强大的自主研发实力&#xff0c;建立了专业的研发团队&#xff0c;通过不断的技术创新&#xff0c;形成了分子诊断、免疫诊断、原子吸收、原子荧光及质谱五大技术平台&#xff0c;并成功…

UE学习记录03----UE5.2 使用拖拽生成模型

0.创建蓝图控件&#xff0c;自己想要展示的样子 1.侦测鼠标拖动 2.创建拖动操作 3.拖动结束时生成模型 3.1创建actor , 创建变量EntityMesh设为可编辑 生成Actor&#xff0c;创建变量EntityMesh设为可编辑 屏幕鼠标位置转化为3D场景位置 4.将texture设置为变量并设为可编辑&am…

【SpringCloud】Stream消息通知使用

文章目录 概述标准MQ 配置POMYML 示例消息发送配置RabbitMQ可视化插件消息消费者 遇到的问题复现解决&#xff1a;修改YML注意 概述 屏蔽底层消息中间件的差异,降低切换成本&#xff0c;统一消息的编程模型 官网&#xff1a; https://spring.io/projects/spring-cloud-stream#…

3、Spring_容器执行

容器执行点 1.整合 druid 连接池 添加依赖 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version> </dependency>1.硬编码方式整合 新建德鲁伊配置 <?xml version"1.…

【Alibaba中间件技术系列】「RocketMQ技术专题」小白专区之领略一下RocketMQ基础之最!

应一些小伙伴们的私信&#xff0c;希望可以介绍一下RocketMQ的基础&#xff0c;那么我们现在就从0开始&#xff0c;进入RocketMQ的基础学习及概念介绍&#xff0c;为学习和使用RocketMQ打好基础&#xff01; RocketMQ是一款快速地、可靠地、分布式、容易使用的消息中间件&#…

AD(第一部分---绘制元件库)

5.元件库介绍及电阻容模型的创建 注&#xff1a;元件库创建是在&#xff0c;以.SchLib结尾的 注&#xff1a;右下角的Panels消失/出现 点击左上角 "视图""状态栏" (快捷键&#xff1a;VS) 此处的SCH Library就是元件库列表 RES____电阻 CAP____电容&am…

数学——七桥问题——图论

当涉及数学&#xff0c;有很多不同的话题可以讨论。你是否有特定的数学领域、概念或问题想要了解更多&#xff1f;以下是一些常见的数学领域和主题&#xff0c;你可以选择一个或者告诉我你感兴趣的具体内容&#xff0c;我将很乐意为你提供更多信息&#xff1a; 代数学&#xff…