新增插件:Sa-Token独立Redis

This commit is contained in:
click33 2021-06-21 21:18:20 +08:00
parent 1ff29b47af
commit 88c9c87de4
14 changed files with 588 additions and 13 deletions

View File

@ -0,0 +1,12 @@
target/
node_modules/
bin/
.settings/
unpackage/
.classpath
.project
.idea/
.factorypath

View File

@ -0,0 +1,71 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-demo-alone-redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- SpringBoot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/>
</parent>
<!-- 定义sa-token版本号 -->
<properties>
<sa-token-version>1.20.0</sa-token-version>
</properties>
<dependencies>
<!-- springboot依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${sa-token-version}</version>
</dependency>
<!-- sa-token整合redis (使用jackson序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>${sa-token-version}</version>
</dependency>
<!-- 提供redis连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- Sa-Token插件独立使用一个Redis -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-alone-redis</artifactId>
<version>${sa-token-version}</version>
</dependency>
<!-- @ConfigurationProperties -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,21 @@
package com.pj;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import cn.dev33.satoken.SaManager;
/**
* Sa-Token整合SpringBoot 示例
* @author kong
*
*/
@SpringBootApplication
public class SaTokenAloneRedisApplication {
public static void main(String[] args) throws ClassNotFoundException {
SpringApplication.run(SaTokenAloneRedisApplication.class, args);
System.out.println("\n启动成功Sa-Token配置如下" + SaManager.getConfig());
}
}

View File

@ -0,0 +1,162 @@
package com.pj.test;
import java.io.Serializable;
import java.util.List;
/**
* ajax请求返回Json格式数据的封装
*/
public class AjaxJson implements Serializable{
private static final long serialVersionUID = 1L; // 序列化版本号
public static final int CODE_SUCCESS = 200; // 成功状态码
public static final int CODE_ERROR = 500; // 错误状态码
public static final int CODE_WARNING = 501; // 警告状态码
public static final int CODE_NOT_JUR = 403; // 无权限状态码
public static final int CODE_NOT_LOGIN = 401; // 未登录状态码
public static final int CODE_INVALID_REQUEST = 400; // 无效请求状态码
public int code; // 状态码
public String msg; // 描述信息
public Object data; // 携带对象
public Long dataCount; // 数据总数用于分页
/**
* 返回code
* @return
*/
public int getCode() {
return this.code;
}
/**
* 给msg赋值连缀风格
*/
public AjaxJson setMsg(String msg) {
this.msg = msg;
return this;
}
public String getMsg() {
return this.msg;
}
/**
* 给data赋值连缀风格
*/
public AjaxJson setData(Object data) {
this.data = data;
return this;
}
/**
* 将data还原为指定类型并返回
*/
@SuppressWarnings("unchecked")
public <T> T getData(Class<T> cs) {
return (T) data;
}
// ============================ 构建 ==================================
public AjaxJson(int code, String msg, Object data, Long dataCount) {
this.code = code;
this.msg = msg;
this.data = data;
this.dataCount = dataCount;
}
// 返回成功
public static AjaxJson getSuccess() {
return new AjaxJson(CODE_SUCCESS, "ok", null, null);
}
public static AjaxJson getSuccess(String msg) {
return new AjaxJson(CODE_SUCCESS, msg, null, null);
}
public static AjaxJson getSuccess(String msg, Object data) {
return new AjaxJson(CODE_SUCCESS, msg, data, null);
}
public static AjaxJson getSuccessData(Object data) {
return new AjaxJson(CODE_SUCCESS, "ok", data, null);
}
public static AjaxJson getSuccessArray(Object... data) {
return new AjaxJson(CODE_SUCCESS, "ok", data, null);
}
// 返回失败
public static AjaxJson getError() {
return new AjaxJson(CODE_ERROR, "error", null, null);
}
public static AjaxJson getError(String msg) {
return new AjaxJson(CODE_ERROR, msg, null, null);
}
// 返回警告
public static AjaxJson getWarning() {
return new AjaxJson(CODE_ERROR, "warning", null, null);
}
public static AjaxJson getWarning(String msg) {
return new AjaxJson(CODE_WARNING, msg, null, null);
}
// 返回未登录
public static AjaxJson getNotLogin() {
return new AjaxJson(CODE_NOT_LOGIN, "未登录,请登录后再次访问", null, null);
}
// 返回没有权限的
public static AjaxJson getNotJur(String msg) {
return new AjaxJson(CODE_NOT_JUR, msg, null, null);
}
// 返回一个自定义状态码的
public static AjaxJson get(int code, String msg){
return new AjaxJson(code, msg, null, null);
}
// 返回分页和数据的
public static AjaxJson getPageData(Long dataCount, Object data){
return new AjaxJson(CODE_SUCCESS, "ok", data, dataCount);
}
// 返回根据受影响行数的(大于0=ok小于0=error)
public static AjaxJson getByLine(int line){
if(line > 0){
return getSuccess("ok", line);
}
return getError("error").setData(line);
}
// 返回根据布尔值来确定最终结果的 (true=okfalse=error)
public static AjaxJson getByBoolean(boolean b){
return b ? getSuccess("ok") : getError("error");
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@SuppressWarnings("rawtypes")
@Override
public String toString() {
String data_string = null;
if(data == null){
} else if(data instanceof List){
data_string = "List(length=" + ((List)data).size() + ")";
} else {
data_string = data.toString();
}
return "{"
+ "\"code\": " + this.getCode()
+ ", \"msg\": \"" + this.getMsg() + "\""
+ ", \"data\": " + data_string
+ ", \"dataCount\": " + dataCount
+ "}";
}
}

View File

@ -0,0 +1,39 @@
package com.pj.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.stp.StpUtil;
/**
* 测试专用Controller
* @author kong
*
*/
@RestController()
@RequestMapping("/test/")
public class TestController {
@Autowired
StringRedisTemplate stringRedisTemplate;
// 测试Sa-Token缓存 浏览器访问 http://localhost:8081/test/login
@RequestMapping("login")
public AjaxJson login(@RequestParam(defaultValue="10001") String id) {
System.out.println("--------------- 测试Sa-Token缓存");
StpUtil.login(id);
return AjaxJson.getSuccess();
}
// 测试业务缓存 浏览器访问 http://localhost:8081/test/test
@RequestMapping("test")
public AjaxJson test() {
System.out.println("--------------- 测试业务缓存");
stringRedisTemplate.opsForValue().set("hello", "Hello World");
return AjaxJson.getSuccess();
}
}

View File

@ -0,0 +1,64 @@
# 端口
server:
port: 8081
spring:
# Sa-Token配置
sa-token:
# Token名称 (同时也是cookie名称)
token-name: satoken
# Token有效期单位s 默认30天, -1代表永不过期
timeout: 2592000
# Token风格
token-style: uuid
# 配置Sa-Token单独使用的Redis连接
alone-redis:
# Redis数据库索引默认为0
database: 2
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码默认为空
password:
# 连接超时时间(毫秒)
timeout: 10ms
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0
# 业务使用的Redis连接
redis:
# Redis数据库索引默认为0
database: 0
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码默认为空
password:
# 连接超时时间(毫秒)
timeout: 10000ms
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0

View File

@ -25,4 +25,13 @@
<module>sa-token-temp-jwt</module>
</modules>
<dependencies>
<!-- spring-boot-configuration -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.0.0.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,12 @@
target/
node_modules/
bin/
.settings/
unpackage/
.classpath
.project
.factorypath
.idea/

View File

@ -0,0 +1,41 @@
<?xml version='1.0' encoding='utf-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-plugin</artifactId>
<version>1.20.0</version>
</parent>
<packaging>jar</packaging>
<name>sa-token-alone-redis</name>
<artifactId>sa-token-alone-redis</artifactId>
<description>sa-token-alone-redis</description>
<dependencies>
<!-- Sa-Token Redis Dependency -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>${sa-token-version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>${sa-token-version}</version>
<optional>true</optional>
</dependency>
<!-- redis pool -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.5.0</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,123 @@
package cn.dev33.satoken.dao.alone;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Lettuce;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.dao.SaTokenDaoDefaultImpl;
import cn.dev33.satoken.dao.SaTokenDaoRedis;
import cn.dev33.satoken.dao.SaTokenDaoRedisJackson;
/**
* SaTokenDao 单独设置Redis连接信息
* @author kong
*/
@Configuration
public class SaAloneRedisInject implements EnvironmentAware{
/**
* 配置信息的前缀
*/
public static final String ALONE_PREFIX = "spring.sa-token.alone-redis";
/**
* Sa-Token 持久层接口
*/
@Autowired(required = false)
public SaTokenDao saTokenDao;
/**
* 开始注入
*/
@Override
public void setEnvironment(Environment environment) {
// 如果为空或者默认实现则不进行任何操作
if(saTokenDao == null || saTokenDao instanceof SaTokenDaoDefaultImpl) {
return;
}
// ------------------- 开始注入
// 获取cfg对象
RedisProperties cfg = Binder.get(environment).bind(ALONE_PREFIX, RedisProperties.class).get();
// 1. Redis配置
RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
redisConfig.setHostName(cfg.getHost());
redisConfig.setPort(cfg.getPort());
redisConfig.setDatabase(cfg.getDatabase());
redisConfig.setPassword(RedisPassword.of(cfg.getPassword()));
// 2. 连接池配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// pool配置
Lettuce lettuce = cfg.getLettuce();
if(lettuce.getPool() != null) {
RedisProperties.Pool pool = cfg.getLettuce().getPool();
// 连接池最大连接数
poolConfig.setMaxTotal(pool.getMaxActive());
// 连接池中的最大空闲连接
poolConfig.setMaxIdle(pool.getMaxIdle());
// 连接池中的最小空闲连接
poolConfig.setMinIdle(pool.getMinIdle());
// 连接池最大阻塞等待时间使用负值表示没有限制
poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis());
}
LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
// timeout
if(cfg.getTimeout() != null) {
builder.commandTimeout(cfg.getTimeout());
}
// shutdownTimeout
if(lettuce.getShutdownTimeout() != null) {
builder.shutdownTimeout(lettuce.getShutdownTimeout());
}
// 创建Factory对象
LettuceClientConfiguration clientConfig = builder.poolConfig(poolConfig).build();
LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfig, clientConfig);
factory.afterPropertiesSet();
// 3. 开始初始化 SaTokenDao
// 如果是SaTokenDaoRedis
try {
Class.forName("cn.dev33.satoken.dao.SaTokenDaoRedis");
SaTokenDaoRedis dao = (SaTokenDaoRedis)saTokenDao;
dao.isInit = false;
dao.init(factory);
return;
} catch (ClassNotFoundException e) {
}
// 如果是SaTokenDaoRedisJackson
try {
Class.forName("cn.dev33.satoken.dao.SaTokenDaoRedisJackson");
SaTokenDaoRedisJackson dao = (SaTokenDaoRedisJackson)saTokenDao;
dao.isInit = false;
dao.init(factory);
return;
} catch (ClassNotFoundException e) {
}
}
/**
* 骗过编辑器增加配置文件代码提示
* @return 配置对象
*/
@ConfigurationProperties(prefix = ALONE_PREFIX)
public RedisProperties getSaAloneRedisConfig() {
return new RedisProperties();
}
}

View File

@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.dev33.satoken.dao.alone.SaAloneRedisInject

View File

@ -36,15 +36,21 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
/**
* String专用
*/
@Autowired
public StringRedisTemplate stringRedisTemplate;
/**
* Object专用
*/
public RedisTemplate<String, Object> objectRedisTemplate;
/**
* 标记是否已初始化成功
*/
public boolean isInit;
@Autowired
public void setObjectRedisTemplate(RedisConnectionFactory connectionFactory) {
public void init(RedisConnectionFactory connectionFactory) {
// 指定相应的序列化方案
StringRedisSerializer keySerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer();
@ -58,6 +64,10 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
} catch (Exception e) {
System.err.println(e.getMessage());
}
// 构建StringRedisTemplate
StringRedisTemplate stringTemplate = new StringRedisTemplate();
stringTemplate.setConnectionFactory(connectionFactory);
stringTemplate.afterPropertiesSet();
// 构建RedisTemplate
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(connectionFactory);
@ -66,8 +76,12 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
template.setValueSerializer(valueSerializer);
template.setHashValueSerializer(valueSerializer);
template.afterPropertiesSet();
if(this.objectRedisTemplate == null) {
// 开始初始化相关组件
if(this.isInit == false) {
this.stringRedisTemplate = stringTemplate;
this.objectRedisTemplate = template;
this.isInit = true;
}
}

View File

@ -27,18 +27,27 @@ public class SaTokenDaoRedis implements SaTokenDao {
/**
* String专用
*/
@Autowired
public StringRedisTemplate stringRedisTemplate;
/**
* Objecy专用
*/
public RedisTemplate<String, Object> objectRedisTemplate;
/**
* 标记是否已初始化成功
*/
public boolean isInit;
@Autowired
public void setObjectRedisTemplate(RedisConnectionFactory connectionFactory) {
public void init(RedisConnectionFactory connectionFactory) {
// 指定相应的序列化方案
StringRedisSerializer keySerializer = new StringRedisSerializer();
JdkSerializationRedisSerializer valueSerializer = new JdkSerializationRedisSerializer();
// 构建StringRedisTemplate
StringRedisTemplate stringTemplate = new StringRedisTemplate();
stringTemplate.setConnectionFactory(connectionFactory);
stringTemplate.afterPropertiesSet();
// 构建RedisTemplate
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(connectionFactory);
@ -47,8 +56,12 @@ public class SaTokenDaoRedis implements SaTokenDao {
template.setValueSerializer(valueSerializer);
template.setHashValueSerializer(valueSerializer);
template.afterPropertiesSet();
if(this.objectRedisTemplate == null) {
// 开始初始化相关组件
if(this.isInit == false) {
this.stringRedisTemplate = stringTemplate;
this.objectRedisTemplate = template;
this.isInit = true;
}
}

View File

@ -28,13 +28,6 @@
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<!-- spring-boot-configuration -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.0.0.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>