SaManager 管理 Sa-Token 所有全局组件,可通过此类快速获取、写入各种全局组件对象
其实也就是框架的context上下文,可以获取到全局组件信息,那么就以为 # SaTokenConfig 为例子说下框架中全局组件如何设计。
Springboot 自动装配
定义在META-INF下的spring.factories中的类全路径,spring会自动帮我们扫描
那么按照框架中的设计,依葫芦画瓢我们也整一个。
配置类 # SaBeanRegister
package com.example.demo.satoken.spirng; import com.example.demo.satoken.config.SaTokenConfigPlus; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; /** * @author Jerry * @date 2024-01-23 11:19 * 注册Sa-Token所需要的Bean * <p> Bean 的注册与注入应该分开在两个文件中,否则在某些场景下会造成循环依赖 */ public class SaBeanRegister { /** * 获取配置Bean * * @return 配置对象 */ @Bean @ConfigurationProperties(prefix = "sa-token-plus") public SaTokenConfigPlus getSaTokenConfigPlus() { return new SaTokenConfigPlus(); } }
可以看到这里注入一个Bean # SaTokenConfigPlus 没错就是我们自定义的类,属性可以配置在Yml文件中,
配置类: # SaTokenConfigPlus
package com.example.demo.satoken.config; import lombok.Data; import java.io.Serializable; /** * @author Jerry * @date 2024-01-23 11:00 * 自定义配置 */ @Data public class SaTokenConfigPlus implements Serializable { private static final long serialVersionUID = -6541180061782004705L; /** token名称 (同时也是cookie名称) */ private String tokenName = "satoken"; /** token的长久有效期(单位:秒) 默认30天, -1代表永久 */ private long timeout = 60 * 60 * 24 * 30; /** * token临时有效期 [指定时间内无操作就视为token过期] (单位: 秒), 默认-1 代表不限制 * (例如可以设置为1800代表30分钟内无操作就过期) */ private long activityTimeout = -1; /** 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) */ private Boolean isConcurrent = true; /** 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) */ private Boolean isShare = true; /** * 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有效) */ private int maxLoginCount = 12; /** 是否尝试从请求体里读取token */ private Boolean isReadBody = true; /** 是否尝试从header里读取token */ private Boolean isReadHead = true; /** 是否尝试从cookie里读取token */ private Boolean isReadCookie = true; /** token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) */ private String tokenStyle = "uuid"; /** 默认dao层实现类中,每次清理过期数据间隔的时间 (单位: 秒) ,默认值30秒,设置为-1代表不启动定时清理 */ private int dataRefreshPeriod = 30; /** 获取[token专属session]时是否必须登录 (如果配置为true,会在每次获取[token-session]时校验是否登录) */ private Boolean tokenSessionCheckLogin = true; /** 是否打开自动续签 (如果此值为true, 框架会在每次直接或间接调用getLoginId()时进行一次过期检查与续签操作) */ private Boolean autoRenew = true; /** token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx) */ private String tokenPrefix; /** 是否在初始化配置时打印版本字符画 */ private Boolean isPrint = true; /** 是否打印操作日志 */ private Boolean isLog = false; /** * jwt秘钥 (只有集成 jwt 模块时此参数才会生效) */ private String jwtSecretKey; /** * Id-Token的有效期 (单位: 秒) */ private long idTokenTimeout = 60 * 60 * 24; /** * Http Basic 认证的账号和密码 */ private String basic = ""; /** 配置当前项目的网络访问地址 */ private String currDomain; /** 是否校验Id-Token(部分rpc插件有效) */ private Boolean checkIdToken = false; }
其实这里字段从sa-token中copy过来的,然后我们就可以在yml中定义自己的配置信息
可以看到idea还会提示我们自定义的配置字段信息
注册到全局组件
配置类 #SaBeanInjectPlus 这个类也是boot自动装配中定义
package com.example.demo.satoken.spirng; import cn.dev33.satoken.stp.StpInterface; import com.example.demo.satoken.config.SaManagerPlus; import com.example.demo.satoken.config.SaTokenConfigPlus; import com.example.demo.satoken.listener.SaTokenEventCenterPlus; import com.example.demo.satoken.listener.SaTokenListenerPlus; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /** * @author Jerry * @date 2024-01-23 11:00 * 注入 Sa-Token 所需要的 Bean */ public class SaBeanInjectPlus { public SaBeanInjectPlus(@Autowired(required = false) SaTokenConfigPlus saTokenConfig) { if (saTokenConfig != null) { SaManagerPlus.setConfig(saTokenConfig); } } }
全局组件 # SaManagerPlus
package com.example.demo.satoken.config; import cn.dev33.satoken.config.SaTokenConfigFactory; import cn.dev33.satoken.stp.StpInterface; import cn.dev33.satoken.stp.StpInterfaceDefaultImpl; /** * @author yueF_L * @version 1.0 * @date 2022-09-08 11:52 * <p> * 管理 Sa-Token 所有全局组 * 自定义测试 */ public class SaManagerPlus { private volatile static SaTokenConfigPlus configPlus; public static void setConfig(SaTokenConfigPlus saTokenConfigPlus) { setConfigPlus(saTokenConfigPlus); } private static void setConfigPlus(SaTokenConfigPlus configPlus) { SaManagerPlus.configPlus = configPlus; } /** * 获取 Sa-Token 的全局配置信息 * * @return 全局配置信息 */ public static SaTokenConfigPlus getConfigPlus() { if (configPlus == null) { synchronized (SaManagerPlus.class) { if (configPlus == null) { // 给默认实现 //setConfigMethod(SaTokenConfigFactory.createConfig()); } } } return configPlus; } private volatile static StpInterface stpInterface; public static void setStpInterface(StpInterface stpInterface) { SaManagerPlus.stpInterface = stpInterface; } public static StpInterface getStpInterface() { if (stpInterface == null) { synchronized (SaManagerPlus.class) { if (stpInterface == null) { setStpInterface(new StpInterfaceDefaultImpl()); } } } return stpInterface; } }
采用双重校验锁的单例模式