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

登录的几种方式

使用Session完成登录

1. 手机号发送验证码

逻辑步骤:
  1. 校验手机号格式是否正确。
  2. 生成验证码(例如使用Hutool工具类)。
  3. 将手机号和验证码存入Session。
  4. 返回验证码发送成功的响应。

2. 用户登录逻辑

逻辑步骤:
  1. 从Session中获取存储的手机号和验证码。
  2. 校验前端传来的手机号和验证码是否与Session中一致。
  3. 如果一致,根据手机号查询用户是否存在。
    • 如果不存在,创建新用户并随机生成用户名。
  4. 将用户信息存入Session。
package com.hmdp.service.impl;import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.servlet.http.HttpSession;import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;/*** <p>* 服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Overridepublic Result sendCode(String phone, HttpSession session) {// 校验手机号if (RegexUtils.isPhoneInvalid(phone)) {// 不符合 返回错误信息return Result.fail("手机号格式错误");}// 生成验证码String code = RandomUtil.randomNumbers(6);// 保存验证码到Sessionsession.setAttribute("code",code);session.setAttribute("phone",phone);//TODO 发送验证码 需要调用第三方log.debug("发送验证码成功,验证码{}",code);// 返回成功return Result.ok();}@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {// 校验手机号和验证码if (!loginForm.getPhone().equals(session.getAttribute("phone"))) {return Result.fail("手机号和之前的不同");}// 校验码不一致,报错if (!session.getAttribute("code").equals(loginForm.getCode())) {return Result.fail("验证码不正确");}// 一致,根据手机号查询用户User user = query().eq("phone", loginForm.getPhone()).one();if (user==null) {// 用户不存在 创建新的用户 保存用户到数据库,保存用户到Sessionuser = createUserWithPhone(loginForm.getPhone());}// 用户存在,直接保存用户到Sessionsession.setAttribute("user",user);return Result.ok();}private User createUserWithPhone(String phone) {User user = new User();user.setPhone(phone);user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10)); // 设置默认的用户名save(user);return user;}
}

3. 登录校验拦截器

逻辑步骤:
  1. 拦截所有需要登录验证的请求。
  2. 检查Session中是否存在user对象。
  3. 如果不存在,返回未登录的错误信息;否则将user信息转换为只含有id,昵称和头像地址的类之后(保护用户隐私信息)存入TreadLocal当中,并且放行。
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Object user = request.getSession().getAttribute("user");if (user == null) {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write("未登录,请先登录");return false;}// 将用户信息存入 ThreadLocal // 为了保护用户的隐私需要专门设置一个类只存储用户的昵id,称和头像地址UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);UserContext.setUser(userDTO );return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清理 ThreadLocal 防止内存泄漏UserContext.clear();}
}

 UserContext 工具类:

public class UserContext {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();}
}

还需要在MvcConfig当中配置拦截器

package com.hmdp.config;import com.hmdp.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/user/code","/user/login","/blog/hot","/shop/**","/shop-type/**","/voucher/**").order(0);}
}

session 在服务器端有默认的时长(过期时间),这是由服务器配置决定的。默认情况下,Session 的有效期会受到服务器设置的影响,而无需手动设置时长。如果需要自定义时长,可以进行配置。 (默认值

在大多数 Servlet 容器(如 Tomcat、Jetty)中,Session 的默认超时时间是 30分钟

这个时间表示,如果用户在 30 分钟内没有访问服务器,Session 会被销毁。)

基于Redis代替Session登录

问题Session 是存储在服务器内存中的,默认情况下每个服务器实例维护自己的 Session 数据。在分布式系统中,不同的请求可能被分配到不同的服务器实例,从而导致无法访问原始 Session。 

虽然 Session 使用方便,但在分布式、高并发、跨平台场景下,其缺点可能带来较大的限制。因此,很多现代应用倾向于采用 无状态认证(如 JWT) 或集中式存储方案(如 Redis)来代替传统的 Session。选择方案时需要根据业务需求、系统架构和可接受的复杂性权衡决定。

1. 手机号发送验证码

逻辑:
  • 校验手机号是否规范。
  • 使用 Hutool 工具生成验证码。
  • 将验证码存入 Redis,设置过期时间为 2 分钟。

2. 用户登录逻辑

逻辑:
  1. 从 Redis 获取验证码,并与前端提交的验证码比对。
  2. 根据手机号查询用户,不存在则创建新用户。
  3. 生成登录令牌(token),将用户信息转换为 Hash 并存入 Redis,设置有效期为 30 分钟。
  4. 返回 token 给前端。
package com.hmdp.service.impl;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import javax.servlet.http.HttpSession;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.*;
import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;/*** <p>* 服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
@Slf4j
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {final private StringRedisTemplate stringRedisTemplate;@Overridepublic Result sendCode(String phone, HttpSession session) {// 校验手机号if (RegexUtils.isPhoneInvalid(phone)) {// 不符合 返回错误信息return Result.fail("手机号格式错误");}// 生成验证码String code = RandomUtil.randomNumbers(6);/*// 保存验证码到Sessionsession.setAttribute("code",code);session.setAttribute("phone",phone);*/// 存储到Redis中stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);//TODO 发送验证码 需要调用第三方log.debug("发送验证码成功,验证码{}",code);// 返回成功return Result.ok();}@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {/*// 校验手机号和验证码if (!loginForm.getPhone().equals(session.getAttribute("phone"))) {return Result.fail("手机号和之前的不同");}// 校验码不一致,报错if (!session.getAttribute("code").equals(loginForm.getCode())) {return Result.fail("验证码不正确");}*///String code = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + loginForm.getPhone());if(code == null || ! code.equals(loginForm.getCode())){return Result.fail("验证码不正确或者手机号错误");}// 一致,根据手机号查询用户User user = query().eq("phone", loginForm.getPhone()).one();if (user==null) {// 用户不存在 创建新的用户 保存用户到数据库,保存用户到Sessionuser = createUserWithPhone(loginForm.getPhone());}// 用户存在,直接保存用户到Session
//        session.setAttribute("user",user);// 保存到Redis中 以hash模式存储// 随机生成一个token作为登录令牌String token  = UUID.randomUUID().toString(true);// 将User对象转为UserDTO 再以token为key,Hash形式存储UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);// 将userDTO转换为mapMap<String, Object> Usermap = BeanUtil.beanToMap(userDTO,new HashMap<>(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue)-> fieldValue.toString()));stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY +token,Usermap);// 设置有效期stringRedisTemplate.expire(LOGIN_USER_KEY+token,LOGIN_USER_TTL,TimeUnit.MINUTES);// 返回tokenreturn Result.ok(token);}private User createUserWithPhone(String phone) {User user = new User();user.setPhone(phone);user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10)); // 设置默认的用户名save(user);return user;}
}

3. 登录拦截器

逻辑:
  1. 从请求头中获取 token
  2. 使用 token 从 Redis 获取用户信息。
  3. 如果用户信息为空,拦截请求。
  4. 将用户信息保存到 ThreadLocal
  5. 刷新 token 的有效期。

 但是如果我们还是只在登录的拦截器当中刷新token的有效值,那么就只会在局部范围内保证token有效。而不是全局范围内,保证用户的token不会过期。

所以我们需要加一层 加一层拦截器(RefreshTokenInterceptor),虽然说是拦截器,但是他不进行拦截操作,拦截操作还是有LoginInterceptor进行拦截。

什么只在 LoginInterceptor 中刷新 token 不够?

局限性

LoginInterceptor 只对需要登录的接口进行拦截。如果用户只访问公开页面或非登录接口(如 /home/shop 等),这些请求不会经过 LoginInterceptor,导致 token 无法刷新。

如果用户长时间浏览公开页面后访问需要登录的页面,可能因 token 过期被迫重新登录,影响用户体验。

全局活跃性保证

用户访问任何页面都应该被视为活跃状态,无论页面是否需要登录,都需要刷新 token 的有效期。单独依赖 LoginInterceptor 只能保证在局部范围(需要登录的接口)内刷新 token

为什么需要 RefreshTokenInterceptor?

  • RefreshTokenInterceptor 的目的是在全局范围内检测 token 并刷新其有效期。
  • 它负责在所有请求(无论是否需要登录)中检查 token,并且将用户保存到TreadLocal当中,但不进行登录状态的校验。
  • 真正的拦截操作(判断用户是否登录)仍由 LoginInterceptor 执行。(LoginInterceptor 可以查看ThreadLocal中是否存在user就可以判断是否登录了)

RefreshTokenInterceptor的代码: 

package com.hmdp.Interceptor;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.hmdp.dto.UserDTO;
import com.hmdp.utils.UserHolder;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.LOGIN_USER_KEY;
import static com.hmdp.utils.RedisConstants.LOGIN_USER_TTL;@RequiredArgsConstructor
public class RefreshTokenInterceptor implements HandlerInterceptor {final StringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 从请求头当中获取tokenString token = request.getHeader("authorization");//如果 string token =  "" ;  这个 token != null,而是 长度为0。所以不可以直接用 == nullif (StrUtil.isBlankIfStr(token)) {response.setStatus(401);return true;}String key = LOGIN_USER_KEY + token;// 从Redis获取用户Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);// 判断userMapif (userMap.isEmpty()) {response.setStatus(401);return true;}// 将userMap转换为BeanUserDTO userDTO= BeanUtil.fillBeanWithMap(userMap, new UserDTO(),false);
//        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);// 保存到ThreadLocal里面UserHolder.saveUser(userDTO);// 刷新token的有效期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();}
}

LoginInterceptor拦截器代码: 

package com.hmdp.Interceptor;
import com.hmdp.dto.UserDTO;
import com.hmdp.utils.UserHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;// 判断是否需要拦截也就是TreadLocal当中是否存在user
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {UserDTO userDTO = UserHolder.getUser();if (userDTO == null) {response.setStatus(401);return  false;}// 有用户放行return  true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();}
}

MvcConfig配置 

package com.hmdp.config;import com.hmdp.Interceptor.LoginInterceptor;
import com.hmdp.Interceptor.RefreshTokenInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@RequiredArgsConstructor
public class MvcConfig implements WebMvcConfigurer {final StringRedisTemplate stringRedisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 拦截所有 执行顺序默认都是0,按照添加顺序执行,指定Order,越小越先执行// token刷新拦截器registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).order(0);// 拦截部分请求registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/user/code","/user/login","blog/hot","/shop/**","/shop-type/**","/voucher/**").order(1);}
}

MvcConfig作为Spring管理的Bean,可以通过构造注入或字段注入获取StringRedisTemplate。由于拦截器实例是手动创建的,MvcConfig需要将StringRedisTemplate显式传递给LoginInterceptor的构造方法。

相关文章:

登录的几种方式

使用Session完成登录 1. 手机号发送验证码 逻辑步骤&#xff1a; 校验手机号格式是否正确。生成验证码&#xff08;例如使用Hutool工具类&#xff09;。将手机号和验证码存入Session。返回验证码发送成功的响应。 2. 用户登录逻辑 逻辑步骤&#xff1a; 从Session中获取存…...

Python学习(5):数据结构

1 列表 1.1 列表方法 列表数据类型支持很多方法&#xff0c;列表对象的所有方法所示如下&#xff1a; list.append(x)&#xff1a;在列表末尾添加一项。 类似于 a[len(a):] [x]。list.extend(iterable)&#xff1a;通过添加来自 iterable 的所有项来扩展列表。 类似于 a[len…...

第五届电网系统与绿色能源国际学术会议(PGSGE 2025)

2025年第五届电网系统与绿色能源国际学术会议(PGSGE 2025) 定于2025年01月10-12日在吉隆坡召开。 第五届电网系统与绿色能源国际学术会议&#xff08;PGSGE 2025&#xff09; 基本信息 会议官网&#xff1a;www.pgsge.org【点击投稿/了解会议详情】 会议时间&#xff1a;202…...

【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 1:背景动机

目录 1 简单概括2 几个重要发现3 主要贡献4 背景知识5 方法简介 论文&#xff1a;Multi-Head Encoding for Extreme Label Classification 作者&#xff1a;Daojun Liang, Haixia Zhang, Dongfeng Yuan and Minggao Zhang 单位&#xff1a;山东大学 代码&#xff1a;https://gi…...

ruckus R510升级到Unleashe后不能访问

ruckus R510 是IPQ4019&#xff0c;升级到Unleashe&#xff0c;它弹窗提示 但是这个IP没办法用&#xff0c;访问不了AP。 必应了一下&#xff0c;官方提示用advance ip scanner扫描。 扫描持续好久&#xff0c;发现IP竟然是从主路由获得。 9090的端口不用填&#xff0c;甚至不…...

初学stm32 --- FSMC驱动LCD屏

目录 FSMC简介 FSMC框图介绍 FSMC通信引脚介绍 FSMC_NWE 的作用 FSMC_NWE 的时序关系 FSMC_NOE 的含义 FSMC_NOE 的典型用途 FSMC_NOE 的时序关系 使用FSMC驱动LCD FSMC时序介绍 时序特性中的 OE ILI9341重点时序&#xff1a; FSMC地址映射 HADDR与FSMC_A关系 LCD的…...

【2025最新计算机毕业设计】基于Spring Boot+Vue影院购票系统(高质量源码,提供文档,免费部署到本地)

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…...

Java 内存溢出(OOM)问题的排查与解决

在 Java 开发中&#xff0c;内存溢出&#xff08;OutOfMemoryError&#xff0c;简称 OOM&#xff09;是一个常见且棘手的问题。相比于数组越界、空指针等业务异常&#xff0c;OOM 问题通常更难定位和解决。本文将通过一次线上内存溢出问题的排查过程&#xff0c;分享从问题表现…...

Android14 CTS-R6和GTS-12-R2不能同时测试的解决方法

背景 Android14 CTS r6和GTS 12-r1之后&#xff0c;tf-console默认会带起OLC Server&#xff0c;看起来olc server可能是想适配ATS(android-test-station)&#xff0c;一种网页版可视化、可配置的跑XTS的方式。这种网页版ATS对测试人员是比较友好的&#xff0c;网页上简单配置下…...

周末总结(2024/01/04)

工作 人际关系核心实践&#xff1a; 要学会随时回应别人的善意&#xff0c;执行时间控制在5分钟以内 坚持每天早会打招呼 遇到接不住的话题时拉低自己&#xff0c;抬高别人(无阴阳气息) 朋友圈点赞控制在5min以内&#xff0c;职场社交不要放在5min以外 职场的人际关系在面对利…...

《Rust权威指南》学习笔记(二)

枚举enum 1.枚举的定义和使用如下图所示&#xff1a; 定义时还可以给枚举的成员指定数据类型&#xff0c;例如&#xff1a;enum IpAddr{V4(u8, u8, u8, u8),V6(String),}。枚举的变体都位于标识符的命名空间下&#xff0c;使用::进行分隔。 2.一个特殊的枚举Option&#xff0…...

Docker 远程访问完整配置教程以及核心参数理解

Docker 远程访问完整配置教程 以下是配置 Docker 支持远程访问的完整教程&#xff0c;包括参数说明、配置修改、云服务器安全组设置、主机防火墙配置&#xff0c;以及验证远程访问的详细步骤。 1. 理解 -H fd:// 参数的作用&#xff08;理解了以后容易理解后面的操作&#xff…...

在ros2 jazzy和gazebo harmonic下的建图导航(cartographer和navigation)实现(基本)

我的github分支&#xff01;&#xff01;&#xff01; 你可以在这里找到相对应的源码。 DWDROME的MOGI分支 来源于&#xff01;&#xff01; MOGI-ROS/Week-3-4-Gazebo-basics 学习分支整理日志 分支概述 这是一个用于个人学习的新分支&#xff0c;目的是扩展基本模型并添加…...

常见的显示器分辨率及其对应的像素数量

显示器的像素数量通常由其分辨率决定&#xff0c;分辨率表示为水平像素数乘以垂直像素数。 720P&#xff08;1280720&#xff09;&#xff1a; 像素数量&#xff1a;约92.16万特点&#xff1a;这是高清标准的一个分辨率&#xff0c;通常用于手机、平板电脑或小型显示器。900P&…...

浅谈分布式共识算法

分布式共识算法 基础概念1、容错2、共识3、拜占庭将军问题4、多数派5、共识算法分类6、ACID&BASE&CAP Paxos1、相关概念2、三种角色3、运行阶段4、Multi Paxos5、总结6、演化 ZAB1、相关概念2、三种角色3、成员状态4、运行阶段5、ZooKeeper流程6、总结 Raft1、相关概念…...

[Linux]redis5.0.x升级至7.x完整操作流程

1. 从官网下载最新版redis&#xff1a; 官网地址&#xff1a;https://redis.io/download 注&#xff1a;下载需要的登录&#xff0c;如果选择使用github账号登录&#xff0c;那么需要提前在github账号中取消勾选“Keep my email addresses private”&#xff08;隐藏我的邮箱…...

Vue项目中生成node_modules文件夹的两种常用方法及npm优势

在Vue项目中生成node_modules文件夹的过程非常简单,主要步骤如下: 1、使用 npm 安装依赖包; 2、使用 yarn 安装依赖包。其中,推荐使用npm安装依赖包,原因如下: 兼容性更广:npm是Node.js的默认包管理工具,具有更高的兼容性。社区支持:npm拥有更大的用户基础和社区支持,…...

(四)基于STM32通过Event Recoder实现时间测量功能

目录 1. 了解Event Recorder 2. 硬件和软件准备 硬件需求 软件需求 3. 配置STM32工程 使用STM32CubeMX初始化项目 配置Event Recorder 4. 实现时间记录功能 初始化Event Recorder 时间间隔计算 配置Debug选项 测量结果查看 5总结 在嵌入式系统开发中&#xff0c;精…...

【Linux】定时运行shell脚本

1、at命令 at命令允许指定Linux系统何时运行脚本&#xff0c;它会将作业提交到队列中&#xff0c;指定shell在什么时候运行该作业。 at 的守护进程 atd 在后台运行&#xff0c;在作业队列中检查待运行的作业。 at 守护进程会检查系统的一个特殊目录&#xff08;一般位于/var/…...

ARM 汇编基础总结

GNU 汇编语法 编写汇编的过程中&#xff0c;其指令、寄存器名等可以全部使用大写&#xff0c;也可以全部使用小写&#xff0c;但是不能大小写混用。 1. 汇编语句的格式 label: instruction comment label即标号&#xff0c;表示地址位置&#xff0c;有些指令前面可能会有标…...

L27.【LeetCode笔记】2 的幂(五种解法)

目录 1.题目 2.自解 方法1:调用log函数 代码 提交结果 方法2:循环 提交结果 3.优解 方法3:位运算n & (n-1) 0 代码 提交结果 方法4:位运算lowbit 代码 提交结果 4.投机取巧的方法 代码 提交结果 1.题目 https://leetcode.cn/problems/power-of-two/?env…...

【MyBatis-Plus】让 MyBatis 更简单高效

如果你曾经使用过 MyBatis&#xff0c;你一定知道它的强大和灵活。然而&#xff0c;随着项目规模的增长&#xff0c;手写 SQL 成为了一件既繁琐又容易出错的事。这时&#xff0c;MyBatis-Plus&#xff08;简称 MP&#xff09;应运而生&#xff0c;它为 MyBatis 增强了许多功能&…...

如何使用OpenCV进行抓图-多线程

前言 需求&#xff1a; 1、如何使用OpenCV捕抓Windows电脑上USB摄像头的流、 2、采用多线程 3、获知当前摄像头的帧率。 这个需求&#xff0c;之前就有做了&#xff0c;但是由于出现了一个问题&#xff0c;人家摄像头的帧率目前都可以达到60帧/s 了&#xff0c;而我的程序…...

解决安装pynini和WeTextProcessing报错问题

点击这里&#xff0c;访问博客 0. 背景 最近在给别人有偿部署ASR-LLM-TTS项目时遇到安装pynini和WeTextProcessing依赖报错的问题&#xff0c;报错信息如下&#xff1a; IC:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt" "-IC:\Program Files…...

数据中台与数据治理服务方案[50页PPT]

本文概述了数据中台与数据治理服务方案的核心要点。数据中台作为政务服务数据化的核心&#xff0c;通过整合各部门业务系统数据&#xff0c;进行建模与加工&#xff0c;以新数据驱动政府管理效率提升与政务服务能力增强。数据治理则聚焦于解决整体架构问题&#xff0c;确保数据…...

springCloud 脚手架项目功能模块:Java分布式锁

文章目录 引言分布式锁产生的原因:集群常用的分布式锁分布式锁的三种实现方式I ZooKeeper 简介zookeeper本质上是一个分布式的小文件存储系zookeeper特性:全局数据一致性II 基于ZooKeeper 实现一个排他锁创建锁获取锁释放锁Apache ZooKeeper客户端III 分布式锁方案非公平锁方…...

一文讲清楚HTTP常见的请求头和应用

文章目录 一文讲清楚HTTP常见的请求头和应用1. 啥是个HTTP请求头2. 常见的请求头&#xff0c;作用和示例3.协商缓存4.会话状态 一文讲清楚HTTP常见的请求头和应用 1. 啥是个HTTP请求头 一句话&#xff0c;说白了就是限定HTTP传输的一些规则参数&#xff0c;比如Accept&#xf…...

ImportError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32‘ not found

这个问题之前遇到过&#xff0c;没有记录&#xff0c;导致今天又花了2小时 原因是没有GLIBC——2.32 使用以下命令查一下有哪些版本&#xff1a; strings /lib/x86_64-linux-gnu/libm.so.6 | grep GLIBC_ 我已经安装好了&#xff0c;所有有2.32版本 原因是当前的ubuntu版本…...

如何安装适配pytorch版本的torchvision

一、对照版本 版本对照pytorch/vision: Datasets, Transforms and Models specific to Computer Vision 二、下载对应版本的torchvision 下载连接1download.pytorch.org/whl/torch_stable.html 下载连接2download.pytorch.org/whl/cu110/torch_stable.html 笔者认为1会比2更…...

UE4_用户控件_3_用户控件输入数据的方法

祝愿大美兰陵越来越好&#xff01; 一、效果展示&#xff1a; 二、先制作一个角色 1、新建个父类为pawn的蓝图类。更名为BP_Image_Character。 2、这个角色只是用于观察场景&#xff0c;并与场景中的物体相碰撞用的&#xff0c;所以不需要骨骼网格体&#xff0c; 3、但是我们…...

以往博客的复习补充——part1

之前没更新是因为期末考试要复习&#xff0c;没空写博客。1月3号才考完&#xff0c;现在有空&#xff0c;打算从头看一遍&#xff0c;既是复习以前知识点&#xff0c;又是对原来的博客进行补充。刚好寒假&#xff0c;有大把时间。 一&#xff0c;希尔排序&#xff08;Shell So…...

数据挖掘——决策树分类

数据挖掘——决策树分类 决策树分类Hunt算法信息增益增益比率基尼指数连续数据总结 决策树分类 树状结构&#xff0c;可以很好的对数据进行分类&#xff1b; 决策树的根节点到叶节点的每一条路径构建一条规则&#xff1b;具有互斥且完备的特点&#xff0c;即每一个样本均被且…...

Kafka 快速实战及基本原理详解解析-01

一、Kafka 介绍 1. MQ 的作用 消息队列&#xff08;Message Queue&#xff0c;简称 MQ&#xff09;是一种用于跨进程通信的技术&#xff0c;核心功能是通过异步消息的方式实现系统之间的解耦。它在现代分布式系统中有着广泛的应用&#xff0c;主要作用体现在以下三个方面&…...

大模型在自动驾驶领域的应用和存在的问题

大模型在自动驾驶领域的应用与挑战 大模型&#xff08;如 GPT-4、BERT等&#xff09;已经在多个领域取得了突破&#xff0c;自动驾驶是其中一个受益颇多的行业。随着人工智能和深度学习的快速发展&#xff0c;自动驾驶技术正在向更加智能化、自动化和安全的方向发展。大模型在…...

【0x0014】HCI_Read_Local_Name命令详解

目录 一、命令概述 二、命令格式 三、返回事件及参数说明 3.1. HCI_Command_Complete 事件 3.2. Status 3.3. Local_Name 四、命令执行流程 4.1. 命令发送 4.2. 控制器接收并处理命令 4.3. 控制器返回结果 4.4. 主机接收并解析事件包 4.5. 示例代码 五、应用场景 …...

理解Java领域中的 DTO、PO 和 VO

在 Java 开发中&#xff0c;DTO&#xff08;Data Transfer Object&#xff09;、PO&#xff08;Persistent Object&#xff09;和 VO&#xff08;Value Object&#xff09;是在不同层面用于数据处理和传递的概念&#xff0c;它们各自有着独特的作用&#xff1a; 一、DTO&#…...

成都和力九垠科技有限公司九垠赢系统Common存在任意文件上传漏洞

免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…...

框架模块说明 #09 日志模块_01

背景 日志模块是系统的重要组成部分&#xff0c;主要负责记录系统运行状态和定位错误问题的功能。通常&#xff0c;日志分为系统日志、操作日志和安全日志三类。虽然分布式数据平台是当前微服务架构中的重要部分&#xff0c;但本文的重点并不在此&#xff0c;而是聚焦于自定义…...

Unity热更文件比较工具类

打包出来的热更文件&#xff0c;如果每次都要全部上传到CDN文件服务器&#xff0c;不进耗费时间长&#xff0c;还浪费流量。 所以让AI写了个简单的文件比较工具类&#xff0c;然后修改了一下可用。记录一下。 路径可自行更改。校验算法这里使用的是MD5&#xff0c;如果使用SH…...

Python性能分析深度解析:从`cProfile`到`line_profiler`的优化之路

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在软件开发过程中,性能优化是提升应用质量和用户体验的关键环节。Python作为广泛应用的高级编程语言,其性能分析工具为开发者提供了强大的…...

EF Core配置及使用

Entity Framework Core是微软官方的ORM框架。 ORM&#xff1a;Object Relational Mapping。让开发者用对象操作的形式操作关系数据库。 EF Core是对于底层ADO.NET Core的封装&#xff0c;因此ADO.NET Core支持的数据库不一定被EF Core支持。 代码创建数据库Code First 建实…...

EPS32基础篇开发

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 开发 EPS32基础篇 前言一、GPIO输入输出GPIO可设置一下4种状态代码示例&#xff1a;检测按键&#xff0c;按下时&#xff1a;LED亮&#xff0c;松开时&#xff0c;LED灭 二、…...

【时时三省】(C语言基础)常见的动态内存错误2

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 对非动态开辟空间内存使用free释放 示例&#xff1a; 这个arr数组是在栈上的 *p指向的就是arr 对非动态空间也用了free ferr只能在动态开辟空间使用 使用free释放一块动态开辟空间的一部分…...

Harmony OS开发-ArkUI框架速成四

程序员Feri一名12年的程序员,做过开发带过团队创过业,擅长Java相关开发、鸿蒙开发、人工智能等,专注于程序员搞钱那点儿事,希望在搞钱的路上有你相伴&#xff01;君志所向,一往无前&#xff01; 1.图标库 1.1 图标库概述 HarmonyOS 图标库为 HarmonyOS 开发者提供丰富的在线图…...

vulnhub Earth靶机

搭建靶机直接拖进来就行 1.扫描靶机IP arp-scan -l 2.信息收集 nmap -sS -A -T4 192.168.47.132 得到两个DNS; 在443端口处会让我们加https dirb https://earth.local/ dirb https://terratest.earth.local/ #页面下有三行数值 37090b59030f11060b0a1b4e0000000000004312170a…...

ScheduledExecutorService详解

ScheduledExecutorService 是 Java 并发工具包 (java.util.concurrent) 中的一个接口&#xff0c;用于在指定的延迟后执行任务&#xff0c;或者以固定的时间间隔周期性执行任务。它是 ExecutorService 的子接口&#xff0c;提供了更强大的调度功能。 ScheduledExecutorService…...

logback日志文件多环境配置路径

项目中遇到问题&#xff0c;springboot项目 本地jar包部署到现场后&#xff0c;经常遇到现场的日志存放的路径会更改&#xff0c;经过查阅&#xff0c;有两种方式&#xff0c;下面简单说明一下。 一、第一种 启动jar包时 添加参数 --logging.configF:\hgtest\config\logback.x…...

判断一个变量是否为NaN

1. JS代码 NaN&#xff08;不是一个数字&#xff0c;但数据类型为number&#xff09;是执行数学运算没有成功&#xff0c;返回失败的结果。 另外&#xff0c;NaN 不等于 NaN 。 //利用 NaN 是唯一一个不等于自身的特点 function _isNaN(val) {if (val ! val) {return true;}ret…...

Flask 快速入门

1. Flask 简介 1.1 什么是 Flask Flask 是一个用 Python 编写的轻量级 Web 框架&#xff0c;被誉为 微框架。它提供基础功能&#xff0c;如路由、请求处理和模板引擎&#xff0c;但不强迫开发者使用特定库或工具&#xff0c;赋予开发人员高度的自由选择权&#xff0c;以满足不…...

性能测试03|JMeter:断言、关联、web脚本录制

目录 一、断言 1、响应断言 2、json断言 3、持续时间断言 二、关联 1、正则表达式介绍 2、正则表达式提取器 3、Xpath提取器 4、JSON提取器 5、JMeter属性 三、web脚本录制 一、断言 定义&#xff1a;让程序自动判断实际的返回结果是否与预期结果保持一致 自动校验…...