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

Sa-Token

简介

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。
官方文档

常见功能

请添加图片描述

登录认证

本框架

  1. 用户提交 name + password 参数,调用登录接口。
  2. 登录成功,返回这个用户的 Token 会话凭证
  3. 用户后续的每次请求,都携带上这个 Token。
  4. 服务器根据 Token 判断此会话是否登录成功。
    请添加图片描述
测试
/*** 登录测试 */
@RestController
@RequestMapping("/acc/")
public class LoginController {// 测试登录  ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456@RequestMapping("doLogin")public SaResult doLogin(String name, String pwd) {// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对 if("zhang".equals(name) && "123456".equals(pwd)) { 会话登录:参数填写要登录的账号id,建议的数据类型:long | int | String, 不可以传入复杂类型,如:User、Admin 等等。Sa-Token 为这个账号创建了一个Token凭证,且通过 Cookie 上下文返回给了前端。StpUtil.login(10001);return SaResult.ok("登录成功");}return SaResult.error("登录失败");}// 查询登录状态  ---- http://localhost:8081/acc/isLogin@RequestMapping("isLogin")public SaResult isLogin() {return SaResult.ok("是否登录:" + StpUtil.isLogin());}// 查询 Token 信息  ---- http://localhost:8081/acc/tokenInfo@RequestMapping("tokenInfo")public SaResult tokenInfo() {return SaResult.data(StpUtil.getTokenInfo());}// 测试注销  ---- http://localhost:8081/acc/logout@RequestMapping("logout")public SaResult logout() {StpUtil.logout();return SaResult.ok();}}

Session

基于 Session 的认证是一种服务器端维护用户会话状态的机制,旨在解决 HTTP 协议无状态的问题

  1. 用户登录:客户端提交用户名和密码至服务器,服务器验证身份后生成唯一的 Session ID,并将用户信息(如角色、权限等)存储在服务器的Session 对象中
  2. Session 传递:服务器通过响应头的 Set-Cookie 字段将 Session ID返回给客户端,客户端浏览器自动保存此 Cookie
  3. 会话验证:后续请求中,客户端自动携带该 Cookie(包含 SessionID),服务器通过 Session ID 查找对应的 Session 对象,验证用户身份
  4. 会话管理:若 Session请添加图片描述
    超时或用户主动登出,服务器销毁 Session 对象,客户端 Cookie 失效

JWT

JWT(JSON Web Token) 是一种开放标准(RFC 7519),用于在网络应用间安全传输 JSON 格式的信息。其核心设计为 紧凑性(体积小)和 自包含性(信息完整无需额外存储),由三部分组成Header 、Payload、Signature

组成
  1. Header(头部)
    包含令牌类型(typ)和签名算法(如 HS256 或 RSA)
{ "alg": "HS256", "typ": "JWT" }

2.Payload(载荷)
存储用户身份信息及其他声明(Claims),分为三类:

  • 注册声明(标准字段):如 sub(用户标识)、exp(过期时间)、iat(签发时间)等。
  • 公共声明(自定义但建议标准化):如用户姓名、角色等。
  • 私有声明(业务自定义):如用户偏好设置。

注意:Payload 内容虽可验证但非加密,避免存储敏感信息(如密码)

  • Signature(签名)
    使用密钥对 Header 和 Payload 的编码结果进行签名,确保数据完整性和真实性。签名是 JWT 安全的核心,密钥泄露将导致伪造风险
流程

请添加图片描述

  1. 用户登录:
    用户提交凭证(如用户名/密码),服务器验证成功后生成 JWT,包含用户身份信息和有效期
  2. Token 下发:服务器将 JWT 返回客户端,客户端需存储于 Cookie、LocalStorage 或 SessionStorage 中。推荐通过Authorization 请求头传递
  3. Token 验证:服务器接收请求后: 解码并验证签名:使用密钥验证数据是否被篡改。 检查有效期:如 exp 字段是否过期。 提取用户信息:直接从
    Payload 中获取用户身份,无需查询数据库
实战

JWT工具类:生成和解析JWT

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;public class JwtUtil {/*** 生成jwt* 使用Hs256算法, 私匙使用固定秘钥** @param secretKey jwt秘钥* @param ttlMillis jwt过期时间(毫秒)* @param claims    设置的信息* @return*/public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 生成JWT的时间long expMillis = System.currentTimeMillis() + ttlMillis;Date exp = new Date(expMillis);// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(exp);return builder.compact();}/*** Token解密** @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个* @param token     加密后的token* @return*/public static Claims parseJWT(String secretKey, String token) {// 得到DefaultJwtParserClaims claims = Jwts.parser()// 设置签名的秘钥.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}}

定义拦截器

import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*** jwt令牌校验的拦截器*/
@Component //生成Bean
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {@Autowiredprivate JwtProperties jwtProperties;/*** 校验jwt** @param request* @param response* @param handler* @return* @throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法,直接放行return true;}//1、从请求头中获取令牌String token = request.getHeader(jwtProperties.getAdminTokenName());//2、校验令牌try {log.info("jwt校验:{}", token);Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info("当前员工id:{}", empId);//前端发一次请求,是一次线程(拦截器,controller,service,mapper共有同一线程) (threadLocal)BaseContext.setCurrentId(empId);//3、通过,放行return true;} catch (Exception ex) {//4、不通过,响应401状态码response.setStatus(401);return false;}}
}

注册拦截器

/*** 配置类,注册web层相关组件*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {@Autowiredprivate JwtTokenAdminInterceptor jwtTokenAdminInterceptor;@Autowiredprivate JwtTokenUserInterceptor jwtTokenUserInterceptor;/*** 注册自定义拦截器  配置路径** @param registry*/protected void addInterceptors(InterceptorRegistry registry) {log.info("开始注册自定义拦截器...");registry.addInterceptor(jwtTokenAdminInterceptor)//在以下路径判断.addPathPatterns("/admin/**")//排除以下路径.excludePathPatterns("/admin/employee/login");}/*** 设置静态资源映射* @param registry*/protected void addResourceHandlers(ResourceHandlerRegistry registry) {log.info("开始设置静态资源映射...");registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}//扩展springmvc框架的消息转化器@Overrideprotected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {log.info("扩展消息转化器...");//创建一个消息转化器对象MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();//需要为消息转化器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据converter.setObjectMapper(new JacksonObjectMapper());//将自己的消息转化器加入容器中converters.add(0,converter);}
}

权限认证

自定义注解+AOP实现

实战(判断管理员)

自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {/*** 必须有某个角色** @return*/String mustRole() default "";}

编写切面类

@Aspect
@Component
public class AuthInterceptor {@Resourceprivate UserService userService;/*** 执行拦截** @param joinPoint* @param authCheck* @return*/@Around("@annotation(authCheck)")public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {String mustRole = authCheck.mustRole();RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();// 当前登录用户User loginUser = userService.getLoginUser(request);UserRoleEnum mustRoleEnum = UserRoleEnum.getEnumByValue(mustRole);// 不需要权限,放行if (mustRoleEnum == null) {return joinPoint.proceed();}// 必须有该权限才通过UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(loginUser.getUserRole());if (userRoleEnum == null) {throw new BusinessException(ErrorCode.NO_AUTH_ERROR);}// 如果被封号,直接拒绝if (UserRoleEnum.BAN.equals(userRoleEnum)) {throw new BusinessException(ErrorCode.NO_AUTH_ERROR);}// 必须有管理员权限if (UserRoleEnum.ADMIN.equals(mustRoleEnum)) {// 用户没有管理员权限,拒绝if (!UserRoleEnum.ADMIN.equals(userRoleEnum)) {throw new BusinessException(ErrorCode.NO_AUTH_ERROR);}}// 通过权限校验,放行return joinPoint.proceed();}
}

补充AOP
切面(Aspect):封装横切逻辑的模块(如日志切面类)
连接点(Join Point):程序执行过程中的特定点(如方法调用、异常抛出)
通知(Advice):切面在连接点执行的操作,分为:

  • 前置通知(Before):方法执行前触发(如权限校验)。
  • 后置通知(After):方法执行后触发(无论是否异常)。
  • 返回通知(AfterReturning):方法正常返回后触发。
  • 异常通知(AfterThrowing):方法抛出异常后触发。
  • 环绕通知(Around):包裹目标方法,控制执行流程(如事务管理)。在连接点执行目标方法调用前后可以自己编写逻辑。
@Aspect
@Component
public class LoggingAspect {@Around("execution(* com.example.service.*.*(..))")public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {// 前置逻辑(如参数校验)Object result = pjp.proceed(); // 调用目标方法// 后置逻辑(如日志记录)return result; // 可修改返回值}
}

切点(Pointcut):定义哪些连接点会被切面拦截(通过表达式指定),在本业务中只有有自定义注解并是admin,AOP就会拦截。

利用Sa-token来进行权限校验

链接

实战

1.引入依赖

<!-- Sa-Token 权限认证 -->
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot-starter</artifactId><version>1.39.0</version>
</dependency>

2.编写配置文件

# Sa-Token 配置
sa-token:# token 名称(同时也是 cookie 名称)token-name: mianshiya# token 有效期(单位:秒) 默认30天,-1 代表永久有效timeout: 2592000# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结active-timeout: -1# 是否允许同一账号多地同时登录(为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)is-concurrent: false# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)is-share: true# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)token-style: uuid# 是否输出操作日志 is-log: true

3.注册Sa-token拦截器

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {// 注册 Sa-Token 拦截器,打开注解式鉴权功能 @Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册 Sa-Token 拦截器,打开注解式鉴权功能 registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");    }
}

4.定义权限与角色获取逻辑
实现 StpInterface 接口。该接口提供了获取当前登录用户的权限和角色的方法,在每次调用鉴权代码时,都会执行接口中的方法。

@Component // 保证此类被 SpringBoot 扫描,完成 Sa-Token 的自定义权限验证扩展 
public class StpInterfaceImpl implements StpInterface {/*** 返回一个账号所拥有的权限码集合 (目前没用)*/@Overridepublic List<String> getPermissionList(Object loginId, String s) {return new ArrayList<>();}/*** 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)*/@Overridepublic List<String> getRoleList(Object loginId, String s) {// 从当前登录用户信息中获取角色User user = (User) StpUtil.getSessionByLoginId(loginId).get(USER_LOGIN_STATE);return Collections.singletonList(user.getUserRole());}
}

5.设备信息获取工具类

/*** 设备工具类*/
public class DeviceUtils {/*** 根据请求获取设备信息**/public static String getRequestDevice(HttpServletRequest request) {String userAgentStr = request.getHeader(Header.USER_AGENT.toString());// 使用 Hutool 解析 UserAgentUserAgent userAgent = UserAgentUtil.parse(userAgentStr);ThrowUtils.throwIf(userAgent == null, ErrorCode.OPERATION_ERROR, "非法请求");// 默认值是 PCString device = "pc";// 是否为小程序if (isMiniProgram(userAgentStr)) {device = "miniProgram";} else if (isPad(userAgentStr)) {// 是否为 Paddevice = "pad";} else if (userAgent.isMobile()) {// 是否为手机device = "mobile";}return device;}/*** 判断是否是小程序* 一般通过 User-Agent 字符串中的 "MicroMessenger" 来判断是否是微信小程序**/private static boolean isMiniProgram(String userAgentStr) {// 判断 User-Agent 是否包含 "MicroMessenger" 表示是微信环境return StrUtil.containsIgnoreCase(userAgentStr, "MicroMessenger")&& StrUtil.containsIgnoreCase(userAgentStr, "MiniProgram");}/*** 判断是否为平板设备* 支持 iOS(如 iPad)和 Android 平板的检测**/private static boolean isPad(String userAgentStr) {// 检查 iPad 的 User-Agent 标志boolean isIpad = StrUtil.containsIgnoreCase(userAgentStr, "iPad");// 检查 Android 平板(包含 "Android" 且不包含 "Mobile")boolean isAndroidTablet = StrUtil.containsIgnoreCase(userAgentStr, "Android")&& !StrUtil.containsIgnoreCase(userAgentStr, "Mobile");// 如果是 iPad 或 Android 平板,则返回 truereturn isIpad || isAndroidTablet;}
}

6.编写方法


// Sa-Token 登录,并指定设备,同端登录互斥
StpUtil.login(user.getId(), DeviceUtils.getRequestDevice(request));
StpUtil.getSession().set(USER_LOGIN_STATE, user);
@Override
public User getLoginUser(HttpServletRequest request) {// 先判断是否已登录Object loginUserId = StpUtil.getLoginIdDefaultNull();if (loginUserId == null) {throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);}// 从数据库查询(追求性能的话可以注释,直接走缓存)User currentUser = this.getById((String) loginUserId);if (currentUser == null) {throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);}return currentUser;
}

7.在方法上添加注解

@SaCheckRole(UserConstant.ADMIN_ROLE)

相关文章:

Sa-Token

简介 Sa-Token 是一个轻量级 Java 权限认证框架&#xff0c;主要解决&#xff1a;登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。 官方文档 常见功能 登录认证 本框架 用户提交 name password 参数&#xff0c;调用登…...

StarRocks 中 CURRENT_TIMESTAMP 和 CURRENT_TIME 分区过滤问题

背景 本文基于Starrocks 3.3.5 最近在进行Starrocks 跑数据的时候&#xff0c;发现了一个SQL 扫描了所有分区的数据&#xff0c;简化后的SQL如下&#xff1a; select date_created from tableA where date_createddate_format(current_time(), %Y-%m-%d %H:%i:%S) limit 20其…...

GithubPages+自定义域名+Cloudfare加速+浏览器收录(2025最新排坑)

前言 最近刷到一个小视频&#xff0c;讲述了选择域名选择的三宗罪&#xff0c;分别是 不要使用 .net&#xff0c;因为它价格贵&#xff0c;但是在顶级域名中的 SEO 效果却不是很好&#xff0c;也就是性价比很低不要使用 .cn&#xff0c;因为国外访问该网站可能会很慢&#xf…...

Canvas粒子系统终极指南:从基础运动到复杂交互的全流程实现

文章目录 一、粒子系统基础架构1.1 粒子数据结构设计1.2 粒子系统管理器 二、基础粒子效果实现2.1 重力场模拟2.2 弹性碰撞效果 三、高级交互实现3.1 鼠标吸引效果3.2 颜色渐变粒子 四、性能优化策略4.1 粒子池复用4.2 分层渲染 五、复杂效果实现5.1 烟花爆炸效果5.2 流体模拟 …...

【QT】新建QT工程(详细步骤)

新建QT工程 1.方法(1)点击new project按钮&#xff0c;弹出对话框&#xff0c;新建即可&#xff0c;步骤如下&#xff1a;(2) 点击文件菜单&#xff0c;选择新建文件或者工程&#xff0c;后续步骤如上 2.QT工程文件介绍(1).pro文件 --》QT工程配置文件(2)main.cpp --》QT工程主…...

详解Http:在QT中使用Http协议

目录 一、HTTP 概述 1、主要特点 2、HTTP 方法 3、HTTP 状态码 4、HTTP 头部 5、HTTP的工作原理 二、在Qt中使用HTTP 1、发送简单的HTTP请求 2、发送POST请求 3、处理异步请求 4、使用QSslConfiguration进行HTTPS 5、 处理JSON响应 6、处理错误 三、总结 一、HTTP…...

Next.js 中间件鉴权绕过漏洞 (CVE-2025-29927) 复现利用与原理分析

免责声明 本文所述漏洞复现方法仅供安全研究及授权测试使用&#xff1b; 任何个人/组织须在合法合规前提下实施&#xff0c;严禁用于非法目的&#xff1b; 作者不对任何滥用行为及后果负责&#xff0c;如发现新漏洞请及时联系厂商并遵循漏洞披露规则。 漏洞原理 Next.js 是一个…...

AI时代的数据底座:火山引擎多模态数据湖的设计与实践

资料来源&#xff1a;火山引擎-开发者社区 随着大模型的发展和应用&#xff0c;文本的边界被拓宽&#xff0c;图像、视频、语音各种模态涌现&#xff0c;并给数据管理、检索、计算带来巨大挑战。 火山引擎多模态数据湖 解决方案则可实现海量结构化、半结构化及非结构化数据的统…...

Numpy用法(二)

一.数组变维 1.1 reshape reshape() 可以改变数组维度&#xff0c;但是返回的是一个新的数组&#xff0c;原数组的形状不会被修改.reshape后产生的新数组是原数组的一个视图&#xff0c;即它与原数组共享相同的数据&#xff0c;但可以有不同的形状或维度&#xff0c;且对视图…...

STM32 IIC通信

目录 IIC简介硬件电路连接I2C时序基本单元IIC完整数据帧MPU6050封装硬件IIC内部电路 IIC简介 IIC&#xff08;Inter-Integrated Circuit&#xff09;是 IIC Bus 简称&#xff0c;中文叫集成电路总线。它是一种串行通信总线&#xff0c;使用多主从架构&#xff0c;由飞利浦公司…...

快速入门 JSON 数据格式

引言 JSON&#xff0c;全称 JavaScript Object Notion&#xff0c;类似于XML&#xff0c;YAML&#xff0c;Properties等&#xff0c;是一种数据交换格式&#xff0c;相比于XML&#xff0c;更简单&#xff0c;更轻量&#xff0c;更容易理解。 JSON vs XML 使用 JSON 目前被广…...

FFmpeg —— 中标麒麟系统下使用FFmpeg内核+Qt界面,制作完整功能音视频播放器(附:源码)

🔔 FFmpeg 相关音视频技术、疑难杂症文章合集(掌握后可自封大侠 ⓿_⓿)(记得收藏,持续更新中…) 程序运行效果...

硬件测试工装设计不合理的补救措施

硬件测试工装设计不合理的补救措施主要包括重新评估设计需求、优化工装结构、强化工装校准与验证。其中&#xff0c;优化工装结构尤其重要&#xff0c;通过结构优化能够有效解决因设计不合理导致的测试准确性下降和可靠性不足的问题。根据工程实践数据&#xff0c;经过优化结构…...

任意文件读取漏洞

fofa语句&#xff1a;body"/vite/client" /fs/etc/passwd?import&raw?? https://35.175.173.157/fs/etc/passwd?import&raw?? http://geometer.dev.mvergely.com/fs/etc/passwd?import&raw??...

如何使用RK平台的spi驱动 spidev

RK平台spidev驱动读取RC522版本号示例 1. 硬件与驱动确认 确认SPI接口连接&#xff1a;RC522的SPI引脚与RK开发板的对应SPI控制器正确连接&#xff08;CS、CLK、MOSI、MISO&#xff09;检查内核配置&#xff1a; Bash # 内核需启用以下配置 CONFIG_SPIy CONFIG_SPI_MASTERy…...

网路传输层UDP/TCP

一、端口号 1.端口号 1.1 五元组 端口号(port)标识了一个主机上进行通信的不同的应用程序. 如图所示, 在一个机器上运行着许多进程, 每个进程使用的应用层协议都不一样, 比如FTP, SSH, SMTP, HTTP等. 当主机接收到一个报文中, 网络层一定封装了一个目的ip标识我这台主机, …...

1.2-WAF\CDN\OSS\反向代理\负载均衡

WAF&#xff1a;就是网站应用防火墙&#xff0c;有硬件类、软件类、云WAF&#xff1b; 还有网站内置的WAF&#xff0c;内置的WAF就是直接嵌在代码中的安全防护代码 硬件类&#xff1a;Imperva、天清WAG 软件&#xff1a;安全狗、D盾、云锁 云&#xff1a;阿里云盾、腾讯云WA…...

Dify 服务器部署指南

1. 系统要求 在开始部署之前&#xff0c;请确保你的服务器满足以下要求&#xff1a; 操作系统&#xff1a;Linux&#xff08;推荐使用 Ubuntu 20.04 或更高版本&#xff09;内存&#xff1a;至少 4GB RAM存储&#xff1a;至少 20GB 可用空间网络&#xff1a;稳定的互联网连接…...

从车间到数字生态:MES如何引领制造业智能化革命‌

在全球制造业加速迈向工业4.0的浪潮中&#xff0c;传统生产模式正经历颠覆性变革。制造执行系统&#xff08;MES&#xff09;作为连接物理车间与数字世界的核心纽带&#xff0c;正从“生产辅助工具”升级为“智能决策大脑”&#xff0c;推动制造业向数据驱动、柔性化与可持续化…...

Error:Flash Download failed

出现这个就是编译器要换...

Spring容器生命周期详解

Spring容器生命周期详解 Spring容器的生命周期从启动到关闭分为多个阶段&#xff0c;包括Bean的加载、实例化、初始化、使用和销毁。以下是详细流程和关键点&#xff1a; 1. 容器启动阶段 1.1 容器实例化 核心接口&#xff1a;BeanFactory&#xff08;基础容器&#xff09;或…...

革新测试管理 2.0丨Storm UTP统一测试管理平台智能化升级与全流程优化

承接上篇&#xff1a;从基础架构到深度协同 在首篇文章《革新测试管理 | 统一测试管理平台如何实现远程、协同、自动化&#xff1f;》中&#xff0c;我们探讨了Storm UTP如何通过云端协作、自动化测试框架和分布式执行能力打破传统测试壁垒。经过一年多的客户实践与技术迭代&a…...

将 char [] str = “hello,you,world” 改为 “world,you,hello“,要求空间复杂度为1

题目&#xff1a; 将 char [] str “hello,you,world” 改为 "world,you,hello",要求空间复杂度为1 &#xff08;也就是使用的变量只能是单个字符或者常数&#xff0c;不能使用数组&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff09; 解…...

运维规则之总结(Summary of Operation and Maintenance Rules)

运维规则之总结 在运维领域&#xff0c;经验和流程往往决定了系统的稳定性与可靠性。一个运维人&#xff0c;总结出了以下10条运维规则&#xff0c;涵盖了从基础管理到高级策略的全面内容&#xff0c;旨在帮助运维人员更好地应对各种挑战&#xff0c;确保系统的平稳运行。 1.…...

MongoDB 创建数据库

MongoDB 创建数据库 引言 MongoDB 是一款高性能、可扩展的 NoSQL 数据库&#xff0c;广泛应用于大数据领域。在 MongoDB 中&#xff0c;创建数据库是进行数据存储的第一步。本文将详细介绍 MongoDB 数据库的创建方法&#xff0c;包括手动创建和自动创建两种方式。 MongoDB 数…...

SpringSecurity OAuth2:授权服务器与资源服务器配置

文章目录 引言一、OAuth2基础概念与架构二、授权服务器配置三、令牌策略与存储方式四、资源服务器配置五、远程令牌验证与内省总结 引言 在现代分布式应用架构中&#xff0c;OAuth2已成为实现安全授权与认证的事实标准。Spring Security对OAuth2提供了全面支持&#xff0c;使开…...

Vue 2 探秘:visible 和 append-to-body 是谁的小秘密?

&#x1f680; Vue 2 探秘&#xff1a;visible 和 append-to-body 是谁的小秘密&#xff1f;&#x1f914; 父组件&#xff1a;identify-list.vue子组件&#xff1a;fake-clue-list.vue 嘿&#xff0c;各位前端探险家&#xff01;&#x1f44b; 今天我们要在 Vue 2 的代码丛林…...

C#高级:启动、中止一个指定路径的exe程序

一、启动一个exe class Program {static void Main(string[] args){string exePath "D:\测试\Test.exe";// 修改为你要运行的exe路径StartProcess(exePath);}private static bool StartProcess(string exePath){// 创建一个 ProcessStartInfo 对象来配置进程启动参…...

windows下安装sublime

sublime4 alpha 4098 版本 下载 可以根据待破解的版本选择下载 https://www.sublimetext.com/dev crack alpha4098 的licence 在----- BEGIN LICENSE ----- TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA12C0 A37081C5 D0316412 4584D…...

Qt 日志输出(重定向)

在软件开发中&#xff0c;日志输出是调试和问题排查的关键手段。Qt框架提供了灵活的日志系统&#xff0c;支持从简单的控制台输出到复杂的自定义日志处理。本文将详细介绍Qt中五种常用的日志输出方法&#xff0c;并附上完整代码示例。 一、使用Qt内置日志函数 Qt提供了五个全局…...

51c嵌入式~MOS~合集1

我自己的原文哦~ https://blog.51cto.com/whaosoft/12074888 一、MOS管&#xff1a;米勒效应、开关损耗以及参数匹配 MOS管即场效应管&#xff08;MOSFET&#xff09;&#xff0c;属于压控型&#xff0c;是一种应用非常广泛的功率型开关元件&#xff0c;在开关电源、逆变器…...

一文详解k8s体系架构知识

0.云原生 1.k8s概念 1. k8s集群的两种管理角色 Master&#xff1a;集群控制节点&#xff0c;负责具体命令的执行过程。master节点通常会占用一股独立的服务器&#xff08;高可用部署建议用3台服务器&#xff09;&#xff0c;是整个集群的首脑。 Master节点一组关键进程&#xf…...

Linux内核软中断分析

一、软中断类型 在Linux内核中&#xff0c;中断处理分为上半部&#xff08;硬中断&#xff09;和下半部。上半部负责快速响应硬件事件&#xff0c;而下半部用于处理耗时任务&#xff0c;避免阻塞系统。下半部有三种机制&#xff1a;软中断&#xff08;Softirq&#xff09;、小任…...

从医疗大模型到综合医疗智能体:算法、架构与路径全流程分析

一、引言 1.1 研究背景与意义 随着信息技术的飞速发展,医疗领域正经历着深刻的变革。医疗智能体作为人工智能技术在医疗行业的重要应用,正逐渐成为提升医疗服务质量、优化医疗流程、促进医疗资源合理分配的关键力量。从最初简单的医疗信息管理系统,到如今能够辅助诊断、制定…...

2025跳槽学习计划

&#xff08;1&#xff09;编程基础&#xff1a; 目录学习资料Chttps://www.bilibili.com/video/BV1z64y1U7hs?spm_id_from333.1387.favlist.content.clickLinuxPytorchhttps://www.bilibili.com/video/BV1if4y147hS?spm_id_from333.1387.favlist.content.clickopencv数据结…...

数据库后续

-- 添加作者字段 alter table t_hero add author varchar(100); -- 更新数据 update t_hero set author "曹雪芹" where id 1; update t_hero set author "曹雪芹" where id 2; update t_hero set author "曹雪芹" where id 3; upd…...

程序员软件工具推荐列表

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 程序员软件工具推荐列表1. Snipaste2. VSCod…...

如何在WordPress中限制用户登录到一台设备

在当今的互联网环境下&#xff0c;许多用户习惯共享账户信息&#xff0c;虽然看似无害&#xff0c;却可能对网站运营产生负面影响。尤其是对于那些经营会员网站和在线课程的平台&#xff0c;限制用户同时登录的设备数量显得尤为重要。本文将详细探讨如何在WordPress中限制用户登…...

基于大模型的自发性气胸全方位预测与诊疗方案研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 二、大模型预测自发性气胸的原理及技术基础 2.1 大模型介绍 2.2 模型构建与训练数据 2.3 模型训练与优化 三、术前风险预测与准备 3.1 术前风险预测指标 3.2 基于预测的术前准备 3.3 手术方案与麻醉方案制定…...

文章记单词 | 第14篇(六级)

一&#xff0c;单词释义 affection&#xff1a;n. 喜爱&#xff0c;钟爱&#xff1b;爱慕之情&#xff1b;感情stream&#xff1a;n. 小河&#xff0c;溪流&#xff1b;一连串&#xff0c;源源不断&#xff1b;水流&#xff0c;气流&#xff1b;vi. 流&#xff0c;流动&#x…...

系统如何查找文件?inode号又是什么?

下面分别详细解释您提到的三个问题&#xff1a; “文件系统怎么定位文件”、“inode 是什么”、“为什么删除后还可能被占用”。 一、文件系统怎么定位文件 1.1 目录与文件名并不直接存储文件数据 在常见的 Unix/Linux 文件系统&#xff08;如 ext4、xfs&#xff09;或类似的…...

Uni-app入门到精通:tabBar节点实现多页面的切换

tabBar节点用于实现多页面的切换。对于一个多tabBar应用&#xff0c;可以通过tabBar节点配置项指定一级导航栏&#xff0c;以及tabBar切换时显示的对应页面。在pages.json中提供tabBar节点配置&#xff0c;不仅是为了方便快速开发导航&#xff0c;更重要的是提示App平台和小程序…...

torchvision中数据集的使用

1、torchvision及其数据集的介绍 1.1 torchvision介绍 torchvision 是 PyTorch 的一个官方库&#xff0c;专门用于计算机视觉任务。它提供了以下核心功能&#xff1a; 预训练模型&#xff1a;如 ResNet、VGG、EfficientNet 等。数据集&#xff1a;内置常用视觉数据集&#xf…...

uniapp开发实战自定义组件形式实现自定义海报功能

在 UniApp 中实现自定义海报功能,可以通过 Canvas 来绘制海报。Canvas 提供了丰富的绘图 API,可以精确控制文字、图片和二维码的位置。下面是一个完整的示例,展示如何创建一个自定义海报组件。 项目结构 假设你的项目结构如下: project-root/ ├── pages/ │ └──…...

Java EE 进阶:MyBatis-plus

MyBatis-plus的介绍 MyBatis-plus是MyBatis的增强工具&#xff0c;在MyBatis的基础上做出加强&#xff0c;只要MyBatis有的功能MyBatis-plus都有。 MyBatis-plus的上手 添加依赖 在我们创建项目的时候&#xff0c;我们需要添加MyBatis-plus和mysql的依赖 MyBatis-plus的依赖…...

信息学奥赛一本通 1514:【例 2】最大半连通子图 | 洛谷 P2272 [ZJOI2007] 最大半连通子图

【题目链接】 ybt 1514&#xff1a;【例 2】最大半连通子图 洛谷 P2272 [ZJOI2007] 最大半连通子图 【题目考点】 1. 图论&#xff1a;强连通分量 缩点 2. 图论&#xff1a;拓扑排序 有向无环图动规 【解题思路】 对于图中任意两顶点u、v&#xff0c;满足u到v或v到u有路径…...

正则表达式-笔记

文章目录 一、正则表达式二、正则表达式的基本语法字符类普通字符非打印字符特殊字符 量词限定符锚点修饰符&#xff08;标记&#xff09; 三、在 Python 中使用正则表达式简单搜索提取信息替换文本 参考 从验证用户输入&#xff0c;到从大量文本中提取特定信息&#xff0c;再到…...

Linux 练习二 LVS的NAT模式

作业 要求&#xff1a;使用LVS的 NAT 模式实现 3 台 RS 的轮询访问。IP地址和主机自己规划。 节点规划 主机角色系统网络IPclientclientredhat 9.5仅主机192.168.60.100/24lvslvsredhat 9.5仅主机 NAT192.168.60.200/24 VIP 192.168.23.8/24 DIPnginxrs1redhat 9.5NAT192.16…...

以科技赋能,炫我云渲染受邀参加中关村文化科技融合影视精品创作研讨会!

在文化与科技深度融合的时代浪潮下&#xff0c;影视创作行业经历着前所未有的变革。影视创作行业发展态势迅猛&#xff0c; 同时也面临着诸多挑战。为促进影视创作行业的创新发展&#xff0c;加强业内交流与合作&#xff0c; 3月25日下午&#xff0c;海淀区文化创意产业协会举办…...

Matlab2024a免费版下载教程

Matlab是一个高性能的数学计算与仿真软件&#xff0c;广泛应用于科学计算、数据分析、算法开发以及工程绘图等多个领域。它提供了强大的矩阵运算能力、丰富的内置函数库以及灵活的编程环境&#xff0c;使得用户能够高效地解决复杂的数学问题。本文&#xff0c;我将为大家详细介…...