v1.15更新

This commit is contained in:
shengzhang 2021-03-23 02:24:37 +08:00
parent c574e7f8d7
commit a8117a8021
30 changed files with 362 additions and 170 deletions

View File

@ -1,11 +1,11 @@
<p align="center">
<img alt="logo" src="https://gitee.com/sz6/sa-token/raw/master/sa-token-doc/doc/logo.png" width="150" height="150">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">sa-token v1.14.0</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">sa-token v1.15.0</h1>
<h4 align="center">这可能是史上功能最全的Java权限认证框架</h4>
<h4 align="center">
<a href="https://gitee.com/sz6/sa-token/stargazers"><img src="https://gitee.com/sz6/sa-token/badge/star.svg"></a>
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/sa--token-v1.14.0-2B9939"></a>
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/sa--token-v1.15.0-2B9939"></a>
<a href="https://github.com/click33/sa-token/stargazers"><img src="https://img.shields.io/github/stars/click33/sa-token"></a>
<a href="https://github.com/click33/sa-token/watchers"><img src="https://img.shields.io/github/watchers/click33/sa-token"></a>
<a href="https://github.com/click33/sa-token/network/members"><img src="https://img.shields.io/github/forks/click33/sa-token"></a>

View File

@ -8,7 +8,7 @@
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<packaging>pom</packaging>
<version>1.14.0</version>
<version>1.15.0</version>
<!-- 项目介绍 -->
<name>sa-token</name>
@ -38,7 +38,7 @@
<!-- 一些属性 -->
<properties>
<sa-token-version>1.14.0</sa-token-version>
<sa-token-version>1.15.0</sa-token-version>
<jdk.version>1.8</jdk.version>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>utf-8</project.reporting.outputEncoding>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</parent>
<packaging>jar</packaging>

View File

@ -53,7 +53,7 @@ public class SaTokenManager {
private static SaTokenDao saTokenDao;
public static void setSaTokenDao(SaTokenDao saTokenDao) {
if(SaTokenManager.saTokenDao != null && (SaTokenManager.saTokenDao instanceof SaTokenDaoDefaultImpl)) {
((SaTokenDaoDefaultImpl)SaTokenManager.saTokenDao).endRefreshTimer();
((SaTokenDaoDefaultImpl)SaTokenManager.saTokenDao).endRefreshThread();
}
SaTokenManager.saTokenDao = saTokenDao;
}
@ -149,7 +149,7 @@ public class SaTokenManager {
public static Map<String, StpLogic> stpLogicMap = new HashMap<String, StpLogic>();
/**
* 向集合中 put 一个 StpLogic
* @param stpLogic
* @param stpLogic StpLogic
*/
public static void putStpLogic(StpLogic stpLogic) {
stpLogicMap.put(stpLogic.getLoginKey(), stpLogic);

View File

@ -4,12 +4,9 @@ package cn.dev33.satoken.dao;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.util.SaTaskUtil;
import cn.dev33.satoken.util.SaTaskUtil.FunctionRunClass;
import cn.dev33.satoken.util.SaTokenInsideUtil;
/**
@ -34,7 +31,7 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
* 构造函数
*/
public SaTokenDaoDefaultImpl() {
initRefreshTimer();
initRefreshThread();
}
@ -166,9 +163,15 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
// --------------------- 定时清理过期数据
/**
* 定时任务对象
* 执行数据清理的线程
*/
public Timer refreshTimer;
public Thread refreshThread;
/**
* 是否继续执行数据清理的线程标记
*/
public boolean refreshFlag;
/**
* 清理所有已经过期的key
@ -183,30 +186,46 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
/**
* 初始化定时任务
*/
public void initRefreshTimer() {
// 如果已经被初始化过了, 则停止它
if(this.refreshTimer != null) {
this.endRefreshTimer();
}
// 开始新的定时任务
if(SaTokenManager.getConfig().getDataRefreshPeriod() < 0) {
public void initRefreshThread() {
// 如果配置了<=0的值则不启动定时清理
if(SaTokenManager.getConfig().getDataRefreshPeriod() <= 0) {
return;
}
int period = SaTokenManager.getConfig().getDataRefreshPeriod() * 1000;
this.refreshTimer = SaTaskUtil.setInterval(new FunctionRunClass() {
@Override
public void run() {
refreshDataMap();
// 启动定时刷新
this.refreshFlag = true;
this.refreshThread = new Thread(() -> {
for (;;) {
try {
try {
// 如果已经被标记为结束
if(refreshFlag == false) {
return;
}
// 执行清理
refreshDataMap();
} catch (Exception e) {
e.printStackTrace();
}
// 休眠N秒
int dataRefreshPeriod = SaTokenManager.getConfig().getDataRefreshPeriod();
if(dataRefreshPeriod <= 0) {
dataRefreshPeriod = 1;
}
Thread.sleep(dataRefreshPeriod * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}, period, period);
});
refreshThread.start();
}
/**
* 结束定时任务
*/
public void endRefreshTimer() {
this.refreshTimer.cancel();
public void endRefreshThread() {
this.refreshFlag = false;
}

View File

@ -298,6 +298,138 @@ public class SaSession implements Serializable {
// ----------------------- 存取值 (类型转换)
/**
* 写值
* @param key 名称
* @param value
*/
public void set(String key, Object value) {
dataMap.put(key, value);
update();
}
/**
* 写值(只有在此key原本无值的时候才会写入)
* @param key 名称
* @param value
*/
public void setDefaultValue(String key, Object value) {
if(has(key) == false) {
dataMap.put(key, value);
update();
}
}
/**
* 取值
* @param key key
* @return
*/
public Object get(String key) {
return dataMap.get(key);
}
/**
*
* 取值 (指定默认值)
* @param <T> 默认值的类型
* @param key key
* @param defaultValue 取不到值时返回的默认值
* @return
*/
public <T> T get(String key, T defaultValue) {
return getValueByDefaultValue(get(key), defaultValue);
}
/**
* 取值 (转String类型)
* @param key key
* @return
*/
public String getString(String key) {
Object value = get(key);
if(value == null) {
return null;
}
return String.valueOf(value);
}
/**
* 取值 (转int类型)
* @param key key
* @return
*/
public int getInt(String key) {
return getValueByDefaultValue(get(key), 0);
}
/**
* 取值 (转long类型)
* @param key key
* @return
*/
public long getLong(String key) {
return getValueByDefaultValue(get(key), 0L);
}
/**
* 取值 (转double类型)
* @param key key
* @return
*/
public double getDouble(String key) {
return getValueByDefaultValue(get(key), 0.0);
}
/**
* 取值 (转float类型)
* @param key key
* @return
*/
public float getFloat(String key) {
return getValueByDefaultValue(get(key), 0.0f);
}
/**
* 取值 (指定转换类型)
* @param <T> 泛型
* @param key key
* @param cs 指定转换类型
* @return
*/
public <T> T getModel(String key, Class<T> cs) {
return getValueByClass(get(key), cs);
}
/**
* 取值 (指定转换类型, 并指定值为Null时返回的默认值)
* @param <T> 泛型
* @param key key
* @param cs 指定转换类型
* @param defaultValue 值为Null时返回的默认值
* @return
*/
@SuppressWarnings("unchecked")
public <T> T getModel(String key, Class<T> cs, Object defaultValue) {
Object value = get(key);
if(valueIsNull(value)) {
return (T)defaultValue;
}
return getValueByClass(value, cs);
}
/**
* 是否含有某个key
* @param key has
* @return 是否含有
*/
public boolean has(String key) {
return !valueIsNull(get(key));
}
// --------- 工具方法
/**
* 判断一个值是否为null
* @param value 指定值
@ -308,52 +440,63 @@ public class SaSession implements Serializable {
}
/**
* 从Session中取值并转化为Object类型
* @param key key
* @return
* 将指定值转化为指定类型
* @param <T> 泛型
* @param obj
* @param cs 类型
* @return 转换后的值
*/
public Object getObject(String key) {
return getAttribute(key);
@SuppressWarnings("unchecked")
protected <T> T getValueByClass(Object obj, Class<T> cs) {
// 如果 obj 本来就是 cs 类型
if(obj != null && obj.getClass().equals(cs)) {
return (T)obj;
}
// 开始转换
String obj2 = String.valueOf(obj);
Object obj3 = null;
if (cs.equals(String.class)) {
obj3 = obj2;
} else if (cs.equals(int.class) || cs.equals(Integer.class)) {
obj3 = Integer.valueOf(obj2);
} else if (cs.equals(long.class) || cs.equals(Long.class)) {
obj3 = Long.valueOf(obj2);
} else if (cs.equals(short.class) || cs.equals(Short.class)) {
obj3 = Short.valueOf(obj2);
} else if (cs.equals(byte.class) || cs.equals(Byte.class)) {
obj3 = Byte.valueOf(obj2);
} else if (cs.equals(float.class) || cs.equals(Float.class)) {
obj3 = Float.valueOf(obj2);
} else if (cs.equals(double.class) || cs.equals(Double.class)) {
obj3 = Double.valueOf(obj2);
} else if (cs.equals(boolean.class) || cs.equals(Boolean.class)) {
obj3 = Boolean.valueOf(obj2);
} else {
obj3 = (T)obj;
}
return (T)obj3;
}
/**
* 从Session中取值并转化为String类型
* @param key key
* @return
* 根据默认值来获取值
* @param <T> 泛型
* @param value
* @param defaultValue 默认值
* @return 转换后的值
*/
public String getString(String key) {
Object value = getObject(key);
if(value == null) {
return null;
}
return String.valueOf(value);
}
/**
* 从Session中取值并转化为int类型如果value为空则返回0
* @param key key
* @return
*/
public int getInt(String key) {
Object value = getObject(key);
@SuppressWarnings("unchecked")
protected <T> T getValueByDefaultValue(Object value, T defaultValue) {
// 如果 obj null则直接返回默认值
if(valueIsNull(value)) {
return 0;
return (T)defaultValue;
}
return Integer.valueOf(String.valueOf(value));
}
/**
* 从Session中取值并转化为long类型如果value为空则返回0
* @param key key
* @return
*/
public long getLong(String key) {
Object value = getObject(key);
if(valueIsNull(value)) {
return 0;
}
return Long.valueOf(String.valueOf(value));
// 开始转换
Class<T> cs = (Class<T>) defaultValue.getClass();
return getValueByClass(value, cs);
}
}

View File

@ -90,6 +90,7 @@ public class StpLogic {
/**
* 在当前会话写入当前tokenValue
* @param tokenValue token值
* @param cookieTimeout Cookie存活时间()
*/
public void setTokenValue(String tokenValue, int cookieTimeout){
SaTokenConfig config = getConfig();

View File

@ -39,6 +39,7 @@ public class StpUtil {
/**
* 在当前会话写入当前tokenValue
* @param tokenValue token值
* @param cookieTimeout Cookie存活时间()
*/
public static void setTokenValue(String tokenValue, int cookieTimeout){
stpLogic.setTokenValue(tokenValue, cookieTimeout);

View File

@ -1,60 +0,0 @@
package cn.dev33.satoken.util;
import java.util.Timer;
import java.util.TimerTask;
/**
* 任务调度Util
* @author kong
*
*/
public class SaTaskUtil {
/**
* 延时指定毫秒执行一个函数
* @param fc 要执行的函数
* @param delay 延时的毫秒数
* @return timer任务对象
*/
public static Timer setTimeout(FunctionRunClass fc, int delay) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
fc.run();
timer.cancel();
}
}, delay);
return timer;
}
/**
* 延时delay毫秒每隔period毫秒执行一个函数
* @param fc 要执行的函数
* @param delay 延时的毫秒数
* @param period 每隔多少毫秒执行一次
* @return timer任务对象
*/
public static Timer setInterval(FunctionRunClass fc, int delay, int period) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
fc.run();
}
}, delay, period);
return timer;
}
/**
* 封装一个内部类便于操作
* @author kong
*/
public static interface FunctionRunClass{
/**
* 要执行的方法
*/
public void run();
}
}

View File

@ -13,7 +13,7 @@ public class SaTokenConsts {
/**
* sa-token 版本号
*/
public static final String VERSION_NO = "v1.14.0";
public static final String VERSION_NO = "v1.15.0";
/**
* sa-token 开源地址

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</parent>
<packaging>jar</packaging>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</parent>
<packaging>jar</packaging>

View File

@ -16,7 +16,7 @@
<!-- 定义sa-token版本号 -->
<properties>
<sa-token-version>1.14.0</sa-token-version>
<sa-token-version>1.15.0</sa-token-version>
</properties>
<dependencies>

View File

@ -17,7 +17,7 @@
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<!-- 定义sa-token版本号 -->
<sa-token-version>1.14.0</sa-token-version>
<sa-token-version>1.15.0</sa-token-version>
</properties>
<dependencies>

View File

@ -17,7 +17,7 @@
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<!-- 定义sa-token版本号 -->
<sa-token-version>1.14.0</sa-token-version>
<sa-token-version>1.15.0</sa-token-version>
</properties>
<dependencies>
@ -39,7 +39,7 @@
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-oauth2</artifactId>
<version>1.14.0-alpha</version>
<version>1.15.0-alpha</version>
</dependency>
<!-- sa-token整合redis (使用jackson序列化方式) -->

View File

@ -16,7 +16,7 @@
<!-- 定义sa-token版本号 -->
<properties>
<sa-token-version>1.14.0</sa-token-version>
<sa-token-version>1.15.0</sa-token-version>
</properties>
<dependencies>

View File

@ -1,5 +1,6 @@
package com.pj;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

View File

@ -1,11 +1,11 @@
<p align="center">
<img alt="logo" src="https://gitee.com/sz6/sa-token/raw/master/sa-token-doc/doc/logo.png" width="150" height="150">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">sa-token v1.14.0</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">sa-token v1.15.0</h1>
<h4 align="center">这可能是史上功能最全的Java权限认证框架</h4>
<h4 align="center">
<a href="https://gitee.com/sz6/sa-token/stargazers"><img src="https://gitee.com/sz6/sa-token/badge/star.svg"></a>
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/sa--token-v1.14.0-2B9939"></a>
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/sa--token-v1.15.0-2B9939"></a>
<a href="https://github.com/click33/sa-token/stargazers"><img src="https://img.shields.io/github/stars/click33/sa-token"></a>
<a href="https://github.com/click33/sa-token/watchers"><img src="https://img.shields.io/github/watchers/click33/sa-token"></a>
<a href="https://github.com/click33/sa-token/network/members"><img src="https://img.shields.io/github/forks/click33/sa-token"></a>

View File

@ -21,6 +21,7 @@
<nav>
<select onchange="location.href=this.value">
<option value="http://sa-token.dev33.cn/doc/index.html">最新版</option>
<option value="http://sa-token.dev33.cn/v/v1.14.0/doc/index.html">v1.14.0</option>
<option value="http://sa-token.dev33.cn/v/v1.13.0/doc/index.html">v1.13.0</option>
<option value="http://sa-token.dev33.cn/v/v1.12.1/doc/index.html">v1.12.1</option>
<option value="http://sa-token.dev33.cn/v/v1.12.0/doc/index.html">v1.12.0</option>
@ -43,7 +44,7 @@
</div>
<script>
var name = '<img style="width: 50px; height: 50px; vertical-align: middle;" src="logo.png" alt="logo" /> ';
name += '<b style="font-size: 24px; vertical-align: middle;">sa-token</b> <sub>v1.14.0</sub>'
name += '<b style="font-size: 24px; vertical-align: middle;">sa-token</b> <sub>v1.15.0</sub>'
window.$docsify = {
name: name, // 名字
repo: 'https://github.com/click33/sa-token', // github地址

View File

@ -1,5 +1,26 @@
# 更新日志
### 2021-3-23 @v1.15.0
- 新增:文档添加源码涉及技术栈说明
- 优化:优化路由拦截器模块文档,更简洁的示例
- 修复修复非web环境下的错误提示Request->Response
- 修复修复Cookie注入时path判断错误感谢@zhangzi0291提供的PR
- 新增文档集成Redis章节新增redis配置示例说明感谢群友 `@-)` 提供的建议
- 新增增加token前缀模式可在配置token读取前缀适配`Bearer token`规范 **[重要]**
- 优化:`SaTokenManager`初始化Bean去除`initXxx`方法,优化代码逻辑
- 新增:`SaTokenManager`新增`stpLogicMap`集合,记录所有`StpLogic`的初始化,方便查找
- 新增:`Session`新增timeout操作API可灵活修改Session的剩余有效时间
- 新增token前缀改为强制校验模式如果配置了前缀则前端提交token时必须带有
- 优化:精简`SaRouteInterceptor`,只保留自定义验证和默认的登陆验证,去除冗余功能
- 优化:`SaRouterUtil`迁移到core核心包优化依赖架构
- 优化默认Dao实现类里`Timer定时器`改为子线程 + sleep 模拟
- 新增:`Session`新增各种类型转换API可快速方便存取值 **[重要]**
- 升级注意:
- `SaRouterUtil`类迁移到核心包注意更换import地址
- `SaRouteInterceptor`去出冗余API详情参考路由鉴权部分
### 2021-3-12 @v1.14.0
- 新增:新增`SaLoginModel`登录参数Model适配 [记住我] 模式 **[重要]**
- 新增:新增 `StpUtil.setLoginId()` 时指定token有效期可灵活控制用户的一次登录免验证时长

View File

@ -9,14 +9,14 @@
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</dependency>
```
## Gradle依赖
Gradle用户引入依赖
```
implementation 'cn.dev33:sa-token-spring-boot-starter:1.14.0'
implementation 'cn.dev33:sa-token-spring-boot-starter:1.15.0'
```

View File

@ -19,7 +19,7 @@
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</dependency>
```

View File

@ -21,7 +21,7 @@ sa-token内置两种模式完成注解鉴权分别是`AOP模式`和`拦截器
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-aop</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</dependency>
```

View File

@ -14,7 +14,7 @@ Sa-token默认将会话数据保存在内存中此模式读写速度最快
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</dependency>
```
优点兼容性好缺点Session序列化后基本不可读对开发者来讲等同于乱码
@ -26,7 +26,7 @@ Sa-token默认将会话数据保存在内存中此模式读写速度最快
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</dependency>
```
优点Session序列化后可读性强可灵活手动修改缺点兼容性稍差

View File

@ -65,32 +65,97 @@ SaSessionCustomUtil.deleteSessionById("goods-10001");
### Session相关操作
那么获取到的`SaSession`具体有哪些方法可供操作?
``` java
session.getId(); // 返回此Session的id
session.getCreateTime(); // 返回此Session的创建时间 (时间戳)
session.getAttribute('name'); // 在Session上获取一个值
session.getAttribute('name', 'zhang'); // 在Session上获取一个值并指定取不到值时返回的默认值
session.setAttribute('name', 'zhang'); // 在Session上写入一个值
session.removeAttribute('name'); // 在Session上移除一个值
session.clearAttribute(); // 清空此Session的所有值
session.containsAttribute('name'); // 获取此Session是否含有指定key (返回true或false)
session.attributeKeys(); // 获取此Session会话上所有key (返回Set<String>)
session.getDataMap(); // 返回此Session会话上的底层数据对象如果更新map里的值请调用session.update()方法避免产生脏数据)
session.update(); // 将这个Session从持久库更新一下
session.logout(); // 注销此Session会话 (从持久库删除此Session)
// 返回此Session的id
session.getId();
// 返回此Session的创建时间 (时间戳)
session.getCreateTime();
// 在Session上获取一个值
session.getAttribute('name');
// 在Session上获取一个值并指定取不到值时返回的默认值
session.getAttribute('name', 'zhang');
// 在Session上写入一个值
session.setAttribute('name', 'zhang');
// 在Session上移除一个值
session.removeAttribute('name');
// 清空此Session的所有值
session.clearAttribute();
// 获取此Session是否含有指定key (返回true或false)
session.containsAttribute('name');
// 获取此Session会话上所有key (返回Set<String>)
session.attributeKeys();
// 返回此Session会话上的底层数据对象如果更新map里的值请调用session.update()方法避免产生脏数据)
session.getDataMap();
// 将这个Session从持久库更新一下
session.update();
// 注销此Session会话 (从持久库删除此Session)
session.logout();
```
### 类型转换API
由于Session存取值默认的类型都是Object因此我们通常会写很多不必要类型转换代码 <br>
为了简化操作sa-token自`v1.15.0`封装了存取值API的类型转换你可以非常方便的调用以下方法
``` java
// 写值
session.set("name", "zhang");
// 写值(只有在此key原本无值的时候才会写入)
session.set("name", "zhang");
// 取值
session.get("name");
// 取值 (指定默认值)
session.get("name", "<defaultValue>");
// 取值 (转String类型)
session.getString("name");
// 取值 (转int类型)
session.getInt("age");
// 取值 (转long类型)
session.getLong("age");
// 取值 (转double类型)
session.getDouble("result");
// 取值 (转float类型)
session.getFloat("result");
// 取值 (指定转换类型)
session.getModel("key", Student.class);
// 取值 (指定转换类型, 并指定值为Null时返回的默认值)
session.getModel("key", Student.class, <defaultValue>);
// 是否含有某个key
session.has("key");
```
具体可参考`javax.servlet.http.HttpSession``SaSession`所含方法与其大体类似
### Session环境隔离说明
在springboot环境下取得的session环境和通过StpUtil获取的session环境并不相通, 示例
有同学经常会把 `SaSession``HttpSession` 进行混淆,例如:
``` java
@PostMapping("/resetPoints")
public void reset(HttpSession session) {
session.setAttribute("pointsKey", 66);
SaSession session2 = StpUtil.getSession();
Object value = session2.getAttribute("pointsKey");
System.out.println(value)
// 输出null
// 在HttpSession上写入一个值
session.setAttribute("name", 66);
// 在SaSession进行取值
System.out.println(StpUtil.getSession().getAttribute("name")); // 输出null
}
```
而且, 在使用sa-token多账号模式下, 不同的StpUtil获取的session之间也是环境隔离
**要点:**
1. `SaSession``HttpSession` 没有任何关系,在`HttpSession`上写入的值,在`SaSession`中无法取出
2. `HttpSession`并未被框架接管在使用sa-token时请在任何情况下均使用`SaSession`,不要使用`HttpSession`

View File

@ -41,7 +41,7 @@
<!-- 内容部分 -->
<div class="main-box">
<div class="content-box">
<h1>sa-token<small>v1.14.0</small></h1>
<h1>sa-token<small>v1.15.0</small></h1>
<div class="sub-title">这可能是史上功能最全的java权限认证框架</div>
<!-- <p>0配置开箱即用低学习成本</p> -->
<p>登录验证、权限验证、Session会话、踢人下线、集成Redis、分布式会话、单点登录、前后台分离、记住我模式、模拟他人账号、临时身份切换、多账号体系、注解式鉴权、路由拦截式鉴权、花式token、自动续签、同端互斥登录、会话治理、密码加密、jwt集成、Spring集成...</p>

View File

@ -7,13 +7,13 @@
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</parent>
<packaging>jar</packaging>
<name>sa-token-dao-redis</name>
<artifactId>sa-token-oauth2</artifactId>
<version>1.14.0-alpha</version>
<version>1.15.0-alpha</version>
<description>sa-token realization oauth2.0</description>
<dependencies>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</parent>
<packaging>jar</packaging>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>1.14.0</version>
<version>1.15.0</version>
</parent>
<packaging>jar</packaging>

View File

@ -40,7 +40,7 @@ public class SaTokenServletSpringImpl implements SaTokenServlet {
/**
* 获取路由匹配器
* @param pathMatcher 路由匹配器
* @return 路由匹配器
*/
public static PathMatcher getPathMatcher() {
if(pathMatcher == null) {