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

【 Redis | 实战篇 短信登录 】

前言:

主要完成了基于Session实现登录,解决集群的Session共享问题,从而实现了基于Redis来实现共享Session登录

1.基于Session实现登录

1.1.发送短信验证码

步骤:

前端提交手机号

==》校验手机号

==》不符合返回错误信息,符合生成验证码

==》保存验证码到Session(应该保存手机号与验证码)

==》发送验证码

==》返回数据

 

 解释:我们这个是以手机号为唯一标识,前端提交用户输入的手机号,后端校验手机号的格式,符合就生成一个随机6位的数字验证码,并保存到Session中为了后续登录与注册时校验用户验证码是否填写正确)(当然这里应该保存手机号与验证码,不然会有一个错误)

1.2.短信验证码实现登录与注册

步骤:

前端提交手机号和验证码

==》校验手机号和验证码

==》不通过返回错误信息,通过根据手机号查询用户信息

==》判断用户是否存在

==》不存在,创建新用户,并且保存到数据库中

==》最终存在与不存在都将保存用户到Session中(方便后续校验登录状态)

==》结束

 

 @Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {//获取缓存数据Object catchPhone = session.getAttribute("phone");Object catchCode = session.getAttribute("code");//获取登录数据String code = loginForm.getCode();String phone = loginForm.getPhone();//校验if(!code.equals(catchCode) || !phone.equals(catchPhone)){return Result.fail("手机号或验证码错误");}
//        if (RegexUtils.isPhoneInvalid(phone)) {
//            return Result.fail("手机号格式错误");
//        }
//        String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);
//        if(!code.equals(cacheCode)){
//            return Result.fail("验证码错误");
//        }User user = query().eq("phone", phone).one();//判断用户是否存在if(user == null){//不存在User userNew = new User();userNew.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10));userNew.setPhone(phone);user = userNew;//保存数据库save(user);}//添加到SessionUserDTO userDTO = new UserDTO();BeanUtil.copyProperties(user,userDTO);
//        String token = UUID.randomUUID().toString(true);
//        String tokenKey = LOGIN_USER_KEY + token;
//        Map<String, Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(),
//                CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue) -> fieldValue.toString()));
//        stringRedisTemplate.opsForHash().putAll(tokenKey,userMap);session.setAttribute("user",userDTO);
//       stringRedisTemplate.expire(tokenKey,LOGIN_USER_TTL,TimeUnit.MINUTES);return Result.ok();}

解释: 前端提交用户输入的手机号与验证码,后端从Session中取出存入的手机号与验证码与用户提交的相对比,相同那么我们就通过手机号来从数据库中查询用户信息,信息为空,那么我们需要注册一个用户并将其存入数据库中,最终存在与不存在的(我们自己注册了一个用户)都会有一个用户信息,将用户信息存入Session中(这里还有个细节)(方便后续校验登录状态,判断用户是否登录)

 注意:

老师有一个错误,在发送短信验证码的功能实现时,老师只保存了验证码到Session中,那么等到校验验证码来实现登录与注册时,如果我将手机号修改了会怎么样,只要我手机号符合格式一样可以登录与注册,所以我们需要保持前后手机号的一致性,那么存入Session的数据应该是验证码与手机号,然后登录与注册时同时校验手机号与验证码是否一致

1.3.校验登陆状态

步骤:

前端请求携带Cokie

==》后端拦截器从Session中获取用户信息

==》判断用户是否存在

==》不存在不放行,存在放行

 

public class RefreshTokenInterceptor implements HandlerInterceptor {private final StringRedisTemplate stringRedisTemplate;public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//获取请求头tokenString token = request.getHeader("authorization");//判断是否为空if (StrUtil.isBlank(token)) {return true;}
//        HttpSession session = request.getSession();//设置keyString key = LOGIN_USER_KEY + token;//获取Redis中的数据Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);//判断是否为空if(userMap.isEmpty()){return true;}//获取userUserDTO user = BeanUtil.fillBeanWithMap(userMap,new UserDTO(),false);//存入线程中UserHolder.saveUser( user);stringRedisTemplate.expire(key,LOGIN_USER_TTL, TimeUnit.MINUTES);return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();}
}

 解释:因为每次我们都需要写一堆逻辑来判断用户是否存在,那么我们可以使用AOP思想,在具体一点就是使用拦截器,但是后续服务器是不是需要用户信息,还是从Session中取出用户信息吗?不,频繁的访问Session会增加其访问开销并且造成线程不安全,所以我们依旧采用将用户信息存入TreadLocal中(线程安全)

注意:使用拦截器时,前端需要我们返回一些基础数据给它渲染用户信息,而我们之前存入Session的数据是整个用户的数据(包含密码,手机号),这些信息不适合暴露出去,所以对应之前存入Session时的数据需要做一些修改,只需要存一些基础用户信息即可(且存入Session的信息过多也是不好的)

因此我们需要隐藏用户的敏感信息(存入一些需展示的信息即可)

2.集群的Session共享问题

问题介绍:Session的数据一般存储到服务端或Redis中(手动存),而客户端只保存了一个SessionID(通过Cokie传递)(而且每个客户端的SessionID不同),那么当需要访问多个服务端时,Session数据并不共享,就会出现问题

解决:

方案一:服务器之间进行Session的拷贝(内存浪费,有延迟)

方案二:使用Redis存(Redis是存入内存的,访问速度快,多个服务器可以同时访问不会造成内存浪费)

3.基于Redis实现共享Session登录

 

  @Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic Result sendCode(String phone, HttpSession session) {//1.校验手机号if (RegexUtils.isPhoneInvalid(phone)) {return Result.fail("手机号格式错误");}//2.生成验证码String code = RandomUtil.randomNumbers(6);//3.保存验证码stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
//        session.setAttribute("code",code);
//        session.setAttribute("phone",phone);//4.返回验证码log.debug("当前验证码:{}",code);//5.返回return Result.ok();}@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {
//        //获取缓存数据
//        Object catchPhone = session.getAttribute("phone");
//        Object catchCode = session.getAttribute("code");//获取登录数据String code = loginForm.getCode();String phone = loginForm.getPhone();//校验
//        if(!code.equals(catchCode) || !phone.equals(catchPhone)){
//            return Result.fail("手机号或验证码错误");
//        }if (RegexUtils.isPhoneInvalid(phone)) {return Result.fail("手机号格式错误");}String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);if(!code.equals(cacheCode)){return Result.fail("验证码错误");}User user = query().eq("phone", phone).one();//判断用户是否存在if(user == null){//不存在User userNew = new User();userNew.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10));userNew.setPhone(phone);user = userNew;//保存数据库save(user);}//添加到SessionUserDTO userDTO = new UserDTO();BeanUtil.copyProperties(user,userDTO);String token = UUID.randomUUID().toString(true);String tokenKey = LOGIN_USER_KEY + token;Map<String, Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue) -> fieldValue.toString()));stringRedisTemplate.opsForHash().putAll(tokenKey,userMap);
//        session.setAttribute("user",userDTO);stringRedisTemplate.expire(tokenKey,LOGIN_USER_TTL,TimeUnit.MINUTES);return Result.ok(token);}
public class RefreshTokenInterceptor implements HandlerInterceptor {private final StringRedisTemplate stringRedisTemplate;public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//获取请求头tokenString token = request.getHeader("authorization");//判断是否为空if (StrUtil.isBlank(token)) {return true;}
//        HttpSession session = request.getSession();//设置keyString key = LOGIN_USER_KEY + token;//获取Redis中的数据Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);//判断是否为空if(userMap.isEmpty()){return true;}//获取userUserDTO user = BeanUtil.fillBeanWithMap(userMap,new UserDTO(),false);//存入线程中UserHolder.saveUser( user);stringRedisTemplate.expire(key,LOGIN_USER_TTL, TimeUnit.MINUTES);return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();}
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {UserDTO user = UserHolder.getUser();if(user == null){response.setStatus(401);return false;}return true;}}

解释:其实最终我们只需要修改存入Session的部分,改为存入Redis即可

注意:

1.由于先前Session是用户访问一次(就是进行一次操作)就会更新登录凭证的过期时间(防止登录失效),那么我们也需要实现该功能,一般想到是在拦截器中放行之前更新时间,但是由于之前实现的拦截器有特定的拦截路径,那么没有被拦截的路径我们也需要进行更新,所以我们可以在加一个拦截器专门来更新时间(第一个拦截器更新时间,并进行存用户,第二个拦截器进行判断用户是否存在(它有特定的拦截路径),不存在不放行)

2.由于使用的是StringRedisTemplate,它要求key与value都必须为String类型,所以我们需要将数据转换成String类型再存入Redis中

3.注意拦截器的顺序,一般先添加的拦截器先执行(你也可以设置优先级order

@Configuration
public class MvcConfig implements WebMvcConfigurer {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/shop/**","/voucher/**","/shop-type/**","upload/**","/blog/hot","/user/code","/user/login").order(1);registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).order(0).addPathPatterns("/**");}
}

相关文章:

【 Redis | 实战篇 短信登录 】

前言&#xff1a; 主要完成了基于Session实现登录&#xff0c;解决集群的Session共享问题&#xff0c;从而实现了基于Redis来实现共享Session登录 1.基于Session实现登录 1.1.发送短信验证码 步骤&#xff1a; 前端提交手机号 》校验手机号 》不符合返回错误信息&#xff0…...

AI(学习笔记第二课) 使用langchain进行AI开发

文章目录 AI(学习笔记第二课) 使用langchain进行AI开发学习内容&#xff1a;1. 使用背景2.创建python&#xff08;pycharm community版&#xff09;开发环境并连接deepseek2.1 创建python&#xff08;pycharm community版&#xff09;开发环境2.2 创建python工程2.3 写入初始py…...

如何查看某个文件中的特殊符号

Q&#xff1a;如何查看某个文件中的特殊符号&#xff0c;比如说是换行符之类的转义字符&#xff1f; 1&#xff0c;法1&#xff1a;使用cat -A cat -A filename可以看到-A本质上就是-vET&#xff0c;也就是 展示所有的字符&#xff0c;-v是显示非打印字符&#xff0c;这个需…...

venv环境里控制scapy版本和起trex v2.87

要在虚拟环境&#xff08;venv&#xff09;中控制Scapy版本并运行TRex v2.87&#xff0c;您可以按照以下步骤操作&#xff1a; 创建一个新的虚拟环境&#xff1a; python3 -m venv trex-env激活创建的虚拟环境。在Linux或macOS上&#xff1a; source trex-env/bin/activate在Wi…...

第五十四篇 AI与数据分析

一、AI数据分析就像做菜 想象你在厨房做一道新菜&#xff0c;AI数据分析的流程其实非常相似&#xff1a; 买菜&#xff08;获取数据&#xff09; 去市场挑选新鲜蔬菜 从Excel/数据库获取数据例&#xff1a;pd.read_csv(超市销售表.csv) 洗菜切菜&#xff08;清洗数据&#x…...

C++面向对象编程入门:从类与对象说起(一)

C语言是面向过程&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题&#xff0c;而C面向的是对象&#xff0c;关注的是对象&#xff0c;将一件事拆解成多个对象&#xff0c;靠对象之间互交完成。 目录 类的定义 类的两种定义 …...

openwrt之UCI 增删改查(add/get/set /add_list...)

1&#xff0c;引入 UCI是openwrt的统一配置接口&#xff0c;所有的配置文件被存放在/etc/config/下&#xff0c;使用UCI工具操作具体可查询官网中的开发文章&#xff1a; [OpenWrt Wiki] The UCI systemhttps://openwrt.org/docs/guide-user/base-system/uciconifg <secti…...

TypeScript 中,属性修饰符

在 TypeScript 中&#xff0c;属性修饰符&#xff08;Property Modifiers&#xff09;是用于修饰类的属性或方法的关键字&#xff0c;它们可以改变属性或方法的行为和访问权限。TypeScript 提供了三种主要的属性修饰符&#xff1a;public、private 和 protected。此外&#xff…...

LeetCode 3341.到达最后一个房间的最少时间 I:Dijkstra算法(类似深搜)-简短清晰的话描述

【LetMeFly】3341.到达最后一个房间的最少时间 I&#xff1a;Dijkstra算法&#xff08;类似深搜&#xff09;-简短清晰的话描述 力扣题目链接&#xff1a;https://leetcode.cn/problems/find-minimum-time-to-reach-last-room-i/ 有一个地窖&#xff0c;地窖中有 n x m 个房间…...

http重新为https

1.先创建一个配置文件 主要方便实验 可以将主配置文件下的location全部注释掉&#xff0c;方便观察 2.配置新配置文件 server{ listen 80; listen 443 ssl; ssl_certificate /usr/local/nginx/conf.d/ssl/www.kgc.com.crt; ssl_certificate_key /usr/local/nginx/conf…...

2025最新免费视频号下载工具!支持Win/Mac,一键解析原画质+封面

软件介绍 适用于Windows 2025 最新5月蝴蝶视频号下载工具&#xff0c;免费使用&#xff0c;无广告且免费&#xff0c;支持对原视频和封面进行解析下载&#xff0c;亲测可用&#xff0c;现在很多工具都失效了&#xff0c;难得的几款下载视频号工具&#xff0c;大家且用且珍…...

CTF杂项入门(BUUCTF-Misc第一页)

写在前面 题目涵盖&#xff1a;BUUCTF 第一页杂项 涉及工具&#xff1a; 随波逐流、foremost、binwalk、honeyview、010editor、zipperello、archpr、wireshark、cyberchef、QR_Research、PNGCRC爆破、stegsolve、Audacity、河马、D盾、routerpassview、steghide&#xff0c;以…...

碰一碰发视频一键成片功能开发实践与技术解析

在数字化营销与内容传播领域&#xff0c;碰一碰发视频技术凭借便捷的交互体验&#xff0c;已成为实体商业引流的重要手段。而一键成片功能的融入&#xff0c;能够让用户在触碰 NFC 标签后&#xff0c;快速获取高质量的视频内容&#xff0c;进一步提升传播效率。本文将从功能需求…...

【CTFer成长之路】举足轻重的信息搜集

举足轻重的信息搜集 信息搜集 常见的搜集 题目描述: 一共3部分flag docker-compose.yml version: 3.2services:web:image: registry.cn-hangzhou.aliyuncs.com/n1book/web-information-backk:latestports:- 80:80启动方式 docker-compose up -d 题目Flag n1book{info_…...

centos搭建dokcer和vulhub

1、换源阿里云 2、安装docker与docker-compose 下载1.29.2 docker compose sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 如果下载不了&#xff0c;可以…...

Linux系统下使用Kafka和Zookeeper

Apache Kafka 是一个分布式流处理平台,最初由 LinkedIn 开发,后来成为 Apache 软件基金会的顶级项目。它具有高吞吐量、可扩展性、持久性、容错性等特点,主要用于处理实时数据流。 Linux系统下使用Kafka 1.安装 Java Kafka 和 Zookeeper 都是基于 Java 开发的,所以需要先…...

vscode与keil的乱码不兼容问题

都用英文注释 中文注释的话&#xff0c;打开vscode的自动识别格式,如下 解决VSCode中文乱码 自动识别也可以设置识别优先级&#xff0c;把GB2312和UTF8排在自动识别序列前面(因为keil默认就是GB2312) 4.!!!在暂存更改的时候&#xff0c;不要把vscode的设置给暂存了&#xff…...

C++类和对象:构造函数、析构函数、拷贝构造函数

引言 介绍&#xff1a;C类和对象&#xff1a;构造函数、析构函数、拷贝构造函数 _涂色_博主主页 C基础专栏 一、类的默认成员函数 先认识一下类中的默认成员函数&#xff1a; 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。⼀个类…...

【FAQ】HarmonyOS SDK 闭源开放能力 — PDF Kit

1.问题描述&#xff1a; 预览PDF文件&#xff0c;文档上所描述的loadDocument接口&#xff0c;可以返回文件的状态&#xff0c;并无法实现PDF的预览&#xff0c;是否有能预览PDF相关接口&#xff1f; 解决方案&#xff1a; 1、执行loadDocument进行加载PDF文件后&#xff0c…...

Spring Boot 3 + Undertow 服务器优化配置

优化背景 当你的application需要支持瞬时高并发的时候&#xff0c;tomcat已经不在是最优的选择&#xff0c;我们可以改为Undertow&#xff0c;并对其进行优化。 Undertow 是一个轻量级的、高性能的Java Web 服务器&#xff0c;由JBoss 开发并开源。它是基于非阻塞&#xff08;…...

网易游戏 Flink 云原生实践

摘要&#xff1a;本文整理自网易游戏实时计算&数据湖平台负责人林小铂老师和网易游戏大数据开发工程师陈宇智老师&#xff0c;在Flink Forward Asia 2024 云原生专场的分享。主要分为四个部分&#xff1a; 1、背景 2、架构演进 3、实践挑战 4、总结和展望 01.背景 Flink 在…...

使用迁移学习的自动驾驶汽车信息物理系统安全策略

信息物理系统 (CPS) 是一种新兴系统,它通过信息通信基础设施,实现控制系统、传感器、执行器和周围环境等物理组件之间有效的实时通信与协作 (C&C)。自动驾驶汽车 (AV) 是大量采用 CPS 方法的领域之一,旨在通过降低能源消耗和空气污染来改善智慧城市中的人们生活。因此,…...

《算法导论(第4版)》阅读笔记:p11-p13

《算法导论(第4版)》学习第 8 天&#xff0c;p11-p13 总结&#xff0c;总计 3 页。 一、技术总结 无。 二、英语总结(生词&#xff1a;2) 1.precious (1)precious: pretium(“value, worth, price”) adj. of great value(宝贵&#xff0c;珍贵)。 (2)示例 Computing t…...

Qt 编译 sqldrivers之psql

编译postgres pgsql驱动 下载驱动源码修改配置文件编译 下载驱动源码 // 源代码下载 https://download.qt.io/archive/qt/5.15/5.15.2/submodules/驱动目录:qtbase-everywhere-src-5.15.2\src\plugins\sqldrivers 修改配置文件 打开pro文件 右键点击添加库 此处的为debu…...

查看单元测试覆盖率

文章目录 1、POM文件配置2、编写单元测试3、执行单元测试4、查看单元测试覆盖率 1、POM文件配置 pom文件配置jacoco插件 <!-- 生成JaCoCo覆盖率数据插件 --> <plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artif…...

ASP.NET Core 中实现 Markdown 渲染中间件

文章目录 前言一、核心功能二、实现步骤1&#xff09;安装依赖包2&#xff09;创建中间件类3&#xff09;中间件扩展方法4&#xff09;在Program.cs配置5&#xff09;模板文件示例6&#xff09;*.md文件示例7&#xff09;缓存优化8&#xff09;使用示例 三、注意事项总结 前言 …...

AI学习路径

一、AI入门与系统课程 &#xff08;1&#xff09;《开启AI革命&#xff1a;7天从小白到大神》 简介&#xff1a;保姆级教学&#xff0c;覆盖AI基础知识、机器学习、深度学习、自然语言处理&#xff08;NLP&#xff09;、大语言模型&#xff08;LLM&#xff09;等&#xff0c;…...

基于Kubernetes的Apache Pulsar云原生架构解析与集群部署指南(下)

文章目录 k8s安装部署Pulsar集群前期准备版本要求 安装 Pulsar Helm chart管理pulsarClustersBrokersTopic k8s安装部署Pulsar集群 前期准备 版本要求 Kubernetes 集群&#xff0c;版本 1.14 或更高版本Helm v3&#xff08;3.0.2 或更高版本&#xff09;数据持久化&#xff…...

B站搜索关键词全攻略:掌握B站搜索关键词的运作机制

在拥有超过7亿月活用户的B站&#xff0c;每天都有海量视频涌入平台。无论是普通用户还是内容创作者&#xff0c;掌握B站搜索关键词的运作机制&#xff0c;都能极大提升平台体验和内容价值。本文将从用户和创作者双重视角&#xff0c;深入解析B站搜索关键词的应用技巧和优化策略…...

Windows系统安装Cursor与远程调用本地模型QWQ32B实现AI辅助开发

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

DBeaver查询PostgreSQL的只读模式

问题 DBeaver查询PostgreSQL数据表时&#xff0c;注意到经常会出现“Detect unique identifiers" 这个阶段&#xff0c;几乎需要花费10s时间&#xff0c;想着挺浪费时间的。 问题解决办法 把”读取数据表元数据(唯一键)"这个复选框选项去掉&#xff0c;再进行查询…...

C++内存管理与模板初阶详解:从原理到实践

目录&#xff1a; 一、C/C内存管理1. 内存区域划分2. 动态内存管理3. 底层原理&#xff1a;operator new/delete4.new和delete的实现原理5. 定位new&#xff08;了解即可&#xff09; 二、模板初阶1. 泛型编程2. 函数模板实例化隐式实例化&#xff1a;编译器自动推导类型显式实…...

02-GBase 8s 事务型数据库 客户端工具dbaccess

dbaccess概述 数据库产品通常会提供一个命令行客户端工具。 数据库厂商 命令行客户端 Oracle sqlplus MySQL mysql Marladb mysql GBase 8s dbaccess Kingbase ES ksql DM8 disql dbaccess 是 GBase 8s 数…...

【kubernetes】通过Sealos 命令行工具一键部署k8s集群

一、前言 1、sealos安装k8s集群官网&#xff1a;K8s > Quick-start > Deploy-kubernetes | Sealos Docs 2、本文安装的k8s版本为v1.28.9 3、以下是一些基本的安装要求&#xff1a; 每个集群节点应该有不同的主机名。主机名不要带下划线。所有节点的时间需要同步。需要…...

【Pandas】pandas DataFrame abs

Pandas2.2 DataFrame Computations descriptive stats 方法描述DataFrame.abs()用于返回 DataFrame 中每个元素的绝对值 pandas.DataFrame.abs() pandas.DataFrame.abs() 方法用于返回 DataFrame 中每个元素的绝对值。该方法适用于包含数值型数据的 DataFrame&#xff0c;对…...

如何在 C# 和 .NET 中打印 DataGrid

DataGrid 是 .NET 架构中一个功能极其丰富的组件&#xff0c;或许也是最复杂的组件之一。写这篇文章是为了回答“我到底该如何打印 DataGrid 及其内容”这个问题。最初即兴的建议是使用我的屏幕截图文章来截取表单&#xff0c;但这当然无法解决打印 DataGrid 中虚拟显示的无数行…...

使用DEEPSEEK快速修改QT创建的GUI

QT的GUI&#xff0c;本质上是使用XML进行描述的&#xff0c;在QT CREATOR的界面编辑处&#xff0c;按CTRL2 切换到代码视图&#xff0c;CTRL3切换到编辑器视图。 CTRL2 切换到代码视图 CTRL3 切换到编辑器视图 鼠标左键点击代码视图中&#xff0c;按CTRLA → CTRLC复制XML代码…...

前端面试宝典---JavaScript import 与 Node.js require 的区别

import 和 require 来自不同的规范&#xff1a; import 是 ES6&#xff08;ECMAScript 2015&#xff09;模块系统的一部分&#xff0c;是 JavaScript 语言的标准语法 require 是 CommonJS 规范的一部分&#xff0c;最初为 Node.js 环境设计 加载方式&#xff1a; require() …...

C++入门小馆 :多态

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…...

极简远程革命:打破公网桎梏,重塑数字生活新体验

简远程革命&#xff1a;节点小宝&#xff0c;让家庭与职场无缝互联 ——打破公网桎梏&#xff0c;重塑数字生活新体验 引言&#xff1a;当公网IP成为过去式 在2025年的今天&#xff0c;80%的家庭仍因缺乏公网IP而深陷远程访问困境。NAS玩家为端口映射焦头烂额&#xff0c;家长…...

Linux 网络管理 的实战代码示例

涵盖网络接口配置、连接测试、防火墙管理、数据包捕获、服务监控等核心场景。每个示例均附带详细注释和操作说明,帮助您深入理解 Linux 网络管理的实战技巧。 1. 网络接口配置与管理 1.1 使用 ip 命令管理网络接口 ip 是现代 Linux 系统中管理网络的主要工具,功能比 ifcon…...

OPCUA,OPCDA与MODBUS学习笔记

MODBUS与OPC之间的关系是什么&#xff1f; 前言 OPC协议&#xff08;OLE for Process Control&#xff0c;即过程控制的OLE&#xff09;是一种标准化的通信协议&#xff0c;旨在帮助不同厂商的设备、控制系统和软件之间进行数据交换。OPC协议的目标是提供一种统一的接口&…...

千星计划小程序开发方案

千星计划小程序开发方案 &#xff08;基于2025年行业实践与系统需求&#xff09; 一、核心功能架构 1.‌用户管理模块‌ 用户分层管理&#xff1a;普通用户、达人、合伙人三级身份体系&#xff0c;支持身份升级审核与权限配置 实名认证与资质审核&#xff1a;对接公安系统…...

【RAG技术全景解读】从原理到工业级应用实践

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1f6a8; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f50d; 一、技术原理剖析&#x1f4d0; 核心概念图解&#x1f4a1; 核心作用讲解⚙️ 关键技术模块说明⚖️ 技术选型对比 &…...

20250508在WIN10下使用移远的4G模块EC200A-CN直接上网

1、在WIN10/11下安装驱动程序&#xff1a;Quectel_Windows_USB_DriverA_Customer_V1.1.13.zip 2、使用移远的专用串口工具&#xff1a;QCOM_V1.8.2.7z QCOM_V1.8.2_win64.exe 3、配置串口UART42/COM42【移远会自动生成连续三个串口&#xff0c;最小的那一个】 AT命令&#xf…...

室内无人机自主巡检解决方案-自主方案

室内无人机自主巡检解决方案-自主方案 AIBOX-基于离线地图的LIO室内3D空间位置服务...

SpringCloud服务拆分:Nacos服务注册中心 + LoadBalancer服务负载均衡使用

SpringCloud中Nacos服务注册中心 LoadBalancer服务负载均衡使用 前言Nacos工作流程nacos安装docker安装window安装 运行nacos微服务集成nacos高级特性1.服务集群配置方法效果图模拟服务实例宕机 2.权重配置3.环境隔离 如何启动集群节点本地启动多个节点方法 LoadBalancer集成L…...

视频编解码学习9之照相机历史

照相机的发展历史可以追溯到19世纪初&#xff0c;至今已有200多年。以下是照相机技术演进的主要阶段和里程碑&#xff1a; 1. 早期探索阶段&#xff08;1820s-1880s&#xff09; 1826年&#xff1a;法国人尼埃普斯&#xff08;Nicphore Nipce&#xff09;用沥青感光法拍摄《窗…...

物流无人机自动化装卸技术解析!

一、自动化装卸技术模块的技术难点 1. 货物多样性适配 物流场景中货物包装类型、尺寸、材质差异大&#xff0c;如农产品、医疗物资、工业设备等&#xff0c;要求装卸模块具备高度柔性化设计。例如&#xff0c;单元货物需视觉识别系统进行单个抓取&#xff0c;而整托货物需大…...

图形渲染+事件处理最终版

基于之前做的项目图形移动处理-CSDN博客添加了相机&#xff0c;透视投影&#xff0c;鼠标控制图形旋转。虽然个人感觉这个项目用的是一个二维的三角形&#xff0c;给他加透视投影和相机意义不大&#xff0c;因为透视投影是近大远小&#xff0c;我这个程序设置了放大缩小的限制&…...