其实也就是框架的context上下文,可以获取到全局组件信息,那么就以为 # SaTokenConfig 为例子说下框架中全局组件如何设计。
定义在META-INF下的spring.factories中的类全路径,spring会自动帮我们扫描
那么按照框架中的设计,依葫芦画瓢我们也整一个。
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文件中,
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还会提示我们自定义的配置字段信息
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);
}
}
}
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;
}
}
采用双重校验锁的单例模式