From 8fb5fb19739d6fabdd5c0a608ad51e3802b04304 Mon Sep 17 00:00:00 2001 From: sanyang176 Date: Wed, 25 Jun 2025 21:59:54 +0800 Subject: [PATCH 1/2] =?UTF-8?q?satoken=20=E6=B7=BB=E5=8A=A0ehcache?= =?UTF-8?q?=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sa-token-demo/sa-token-demo-ehcache/pom.xml | 59 ++++++++++++ .../java/com/pj/SaTokenDemoApplication.java | 21 +++++ .../java/com/pj/current/GlobalException.java | 20 ++++ .../java/com/pj/test/LoginController.java | 43 +++++++++ .../src/main/resources/application.yml | 22 +++++ sa-token-dependencies/pom.xml | 8 ++ sa-token-plugin/pom.xml | 1 + sa-token-plugin/sa-token-ehcache/pom.xml | 29 ++++++ .../dev33/satoken/config/EhcacheConfig.java | 32 +++++++ .../satoken/dao/SaMapPackageForEhcache.java | 94 +++++++++++++++++++ .../satoken/dao/SaTokenDaoForEhcache.java | 85 +++++++++++++++++ .../plugin/SaTokenPluginForEhcache.java | 16 ++++ .../cn.dev33.satoken.plugin.SaTokenPlugin | 1 + 13 files changed, 431 insertions(+) create mode 100644 sa-token-demo/sa-token-demo-ehcache/pom.xml create mode 100644 sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/SaTokenDemoApplication.java create mode 100644 sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/current/GlobalException.java create mode 100644 sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/test/LoginController.java create mode 100644 sa-token-demo/sa-token-demo-ehcache/src/main/resources/application.yml create mode 100644 sa-token-plugin/sa-token-ehcache/pom.xml create mode 100644 sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/config/EhcacheConfig.java create mode 100644 sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/dao/SaMapPackageForEhcache.java create mode 100644 sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/dao/SaTokenDaoForEhcache.java create mode 100644 sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForEhcache.java create mode 100644 sa-token-plugin/sa-token-ehcache/src/main/resources/META-INF/satoken/cn.dev33.satoken.plugin.SaTokenPlugin diff --git a/sa-token-demo/sa-token-demo-ehcache/pom.xml b/sa-token-demo/sa-token-demo-ehcache/pom.xml new file mode 100644 index 000000000..5a0bf4d1d --- /dev/null +++ b/sa-token-demo/sa-token-demo-ehcache/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + com.pj + sa-token-demo-ehcache + + + + org.springframework.boot + spring-boot-starter-parent + 2.5.14 + + + + + + + 1.44.0 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-aop + + + + + cn.dev33 + sa-token-spring-boot-starter + ${sa-token.version} + + + + + cn.dev33 + sa-token-ehcache + ${sa-token.version} + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + \ No newline at end of file diff --git a/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/SaTokenDemoApplication.java b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/SaTokenDemoApplication.java new file mode 100644 index 000000000..105a522d8 --- /dev/null +++ b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/SaTokenDemoApplication.java @@ -0,0 +1,21 @@ +package com.pj; + +import cn.dev33.satoken.SaManager; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Sa-Token 整合 Caffeine 示例 + * @author click33 + * + */ +@SpringBootApplication +public class SaTokenDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(SaTokenDemoApplication.class, args); + System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig()); + System.out.println(SaManager.getSaTokenDao()); + } + +} diff --git a/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/current/GlobalException.java b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/current/GlobalException.java new file mode 100644 index 000000000..750fc780d --- /dev/null +++ b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/current/GlobalException.java @@ -0,0 +1,20 @@ +package com.pj.current; + +import cn.dev33.satoken.util.SaResult; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * 全局异常处理 + */ +@RestControllerAdvice +public class GlobalException { + + // 全局异常拦截(拦截项目中的所有异常) + @ExceptionHandler + public SaResult handlerException(Exception e) { + e.printStackTrace(); + return SaResult.error(e.getMessage()); + } + +} diff --git a/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/test/LoginController.java b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/test/LoginController.java new file mode 100644 index 000000000..cfd4e82b0 --- /dev/null +++ b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/test/LoginController.java @@ -0,0 +1,43 @@ +package com.pj.test; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; + +@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)) { + 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(); + } + +} diff --git a/sa-token-demo/sa-token-demo-ehcache/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-ehcache/src/main/resources/application.yml new file mode 100644 index 000000000..125398429 --- /dev/null +++ b/sa-token-demo/sa-token-demo-ehcache/src/main/resources/application.yml @@ -0,0 +1,22 @@ +# 端口 +server: + port: 8081 + +# sa-token 配置 +sa-token: + # token 名称 (同时也是 cookie 名称) + token-name: satoken + # token 有效期(单位:秒) 默认30天,-1 代表永久有效 + timeout: 2592000 + # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 + active-timeout: -1 + # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token) + is-share: false + # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) + token-style: uuid + # 是否输出操作日志 + is-log: true + + diff --git a/sa-token-dependencies/pom.xml b/sa-token-dependencies/pom.xml index 1701c9212..9cde1b7c7 100644 --- a/sa-token-dependencies/pom.xml +++ b/sa-token-dependencies/pom.xml @@ -43,6 +43,7 @@ 3.2.0 1.6.4 4.1.0 + 3.10.0 @@ -312,6 +313,13 @@ ${okhttps.version} + + + org.ehcache + ehcache + ${ehcache.version} + + cn.dev33 diff --git a/sa-token-plugin/pom.xml b/sa-token-plugin/pom.xml index 92c9c783a..dc1f01ff9 100644 --- a/sa-token-plugin/pom.xml +++ b/sa-token-plugin/pom.xml @@ -40,6 +40,7 @@ sa-token-serializer-features sa-token-forest sa-token-okhttps + sa-token-ehcache sa-token-redis-template diff --git a/sa-token-plugin/sa-token-ehcache/pom.xml b/sa-token-plugin/sa-token-ehcache/pom.xml new file mode 100644 index 000000000..5e0c4e63e --- /dev/null +++ b/sa-token-plugin/sa-token-ehcache/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + cn.dev33 + sa-token-plugin + ${revision} + ../pom.xml + + jar + + sa-token-ehcache + sa-token-ehcache + sa-token integrate Ehcache + + + + cn.dev33 + sa-token-core + + + org.ehcache + ehcache + + + + \ No newline at end of file diff --git a/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/config/EhcacheConfig.java b/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/config/EhcacheConfig.java new file mode 100644 index 000000000..86c1e03a9 --- /dev/null +++ b/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/config/EhcacheConfig.java @@ -0,0 +1,32 @@ +package cn.dev33.satoken.config; + +import org.ehcache.CacheManager; +import org.ehcache.config.builders.CacheManagerBuilder; + +/** + * Ehcache 配置类 + * + * @author sanyang176 + */ +public class EhcacheConfig { + + /** + * 创建CacheManager + * + * @return CacheManager + */ + public static CacheManager CreateCacheManager() { + CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(); + cacheManager.init(); + return cacheManager; + } + + /** + * 关闭CacheManager + * + * @param cacheManager / + */ + public static void CloseCacheManager(CacheManager cacheManager) { + cacheManager.close(); + } +} diff --git a/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/dao/SaMapPackageForEhcache.java b/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/dao/SaMapPackageForEhcache.java new file mode 100644 index 000000000..666e171db --- /dev/null +++ b/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/dao/SaMapPackageForEhcache.java @@ -0,0 +1,94 @@ +package cn.dev33.satoken.dao; + +import cn.dev33.satoken.config.EhcacheConfig; +import cn.dev33.satoken.dao.timedcache.SaMapPackage; +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import java.time.Duration; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +/** + * Map 包装类 (Ehcache 版) + * + * @author sanyang176 + */ +public class SaMapPackageForEhcache implements SaMapPackage { + + private final Cache cache; + private static final CacheManager cacheManager = EhcacheConfig.CreateCacheManager(); + + /** + * 初始化缓存 + * @param clazzType / 创建cache需要的具体泛型类型 + * @param cacheName / 创建cache的名字 + */ + public SaMapPackageForEhcache(Class clazzType,String cacheName) { + this.cache = cacheManager.createCache( + cacheName, + CacheConfigurationBuilder.newCacheConfigurationBuilder( + String.class, + clazzType, + ResourcePoolsBuilder.heap(Integer.MAX_VALUE) + ).withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(Long.MAX_VALUE))) + ); + } + + /** + * 获取缓存 + */ + @Override + public Object getSource() { + return cache; + } + + /** + * 读 + * + * @param key / + * @return / + */ + @Override + public V get(String key) { + return cache.get(key); + } + + /** + * 写 + * + * @param key / + * @param value / + */ + @Override + public void put(String key, V value) { + cache.put(key, value); + } + + /** + * 删 + * @param key / + */ + @Override + public void remove(String key) { cache.remove(key); } + + /** + * 所有 key + */ + @Override + public Set keySet() { + return StreamSupport.stream(cache.spliterator(), false) + .map(Cache.Entry::getKey) + .collect(Collectors.toSet()); + } + + /** + * CacheManager 关闭 + */ + public void closeCacheManager() { + EhcacheConfig.CloseCacheManager(cacheManager); + } +} diff --git a/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/dao/SaTokenDaoForEhcache.java b/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/dao/SaTokenDaoForEhcache.java new file mode 100644 index 000000000..1ba6a3a0b --- /dev/null +++ b/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/dao/SaTokenDaoForEhcache.java @@ -0,0 +1,85 @@ +package cn.dev33.satoken.dao; + +import cn.dev33.satoken.dao.auto.SaTokenDaoByStringFollowObject; +import cn.dev33.satoken.dao.timedcache.SaTimedCache; +import cn.dev33.satoken.util.SaFoxUtil; + +import java.util.List; + +public class SaTokenDaoForEhcache implements SaTokenDaoByStringFollowObject, SaTokenDao{ + + private static final String DataCacheName = "DataCache"; + private static final String ExpireCacheName = "ExpireCache"; + + public SaTimedCache timedCache = new SaTimedCache( + new SaMapPackageForEhcache<>(Object.class,DataCacheName), + new SaMapPackageForEhcache<>(Long.class,ExpireCacheName) + ); + + // ------------------------ Object 读写操作 + + @Override + public Object getObject(String key) { + return timedCache.getObject(key); + } + + @Override + @SuppressWarnings("unchecked") + public T getObject(String key, Class classType) { + return (T) timedCache.getObject(key); + } + + @Override + public void setObject(String key, Object object, long timeout) { + timedCache.setObject(key, object, timeout); + } + + @Override + public void updateObject(String key, Object object) { + timedCache.updateObject(key, object); + } + + @Override + public void deleteObject(String key) { + timedCache.deleteObject(key); + } + + @Override + public long getObjectTimeout(String key) { + return timedCache.getObjectTimeout(key); + } + + @Override + public void updateObjectTimeout(String key, long timeout) { + timedCache.updateObjectTimeout(key, timeout); + } + + @Override + public List searchData(String prefix, String keyword, int start, int size, boolean sortType) { + return SaFoxUtil.searchList(timedCache.keySet(), prefix, keyword, start, size, sortType); + } + + // --------- 组件生命周期 + + /** + * 组件被安装时,开始刷新数据线程 + */ + @Override + public void init() { + timedCache.initRefreshThread(); + } + + /** + * 组件被卸载时,结束定时任务,不再定时清理过期数据。 并且关闭Ehcache缓存防止内存泄漏 + */ + @Override + public void destroy() { + timedCache.endRefreshThread(); + if(timedCache.dataMap instanceof SaMapPackageForEhcache){ + ((SaMapPackageForEhcache)timedCache.dataMap).closeCacheManager(); + } + if(timedCache.expireMap instanceof SaMapPackageForEhcache){ + ((SaMapPackageForEhcache)timedCache.expireMap).closeCacheManager(); + } + } +} diff --git a/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForEhcache.java b/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForEhcache.java new file mode 100644 index 000000000..3c0fb3cb1 --- /dev/null +++ b/sa-token-plugin/sa-token-ehcache/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForEhcache.java @@ -0,0 +1,16 @@ +package cn.dev33.satoken.plugin; + +import cn.dev33.satoken.SaManager; +import cn.dev33.satoken.dao.SaTokenDaoForEhcache; + +/** + * SaToken 插件安装:DAO 扩展 - Ehcache 版 + * + * @author sanyang176 + */ +public class SaTokenPluginForEhcache implements SaTokenPlugin{ + @Override + public void install() { + SaManager.setSaTokenDao(new SaTokenDaoForEhcache()); + } +} diff --git a/sa-token-plugin/sa-token-ehcache/src/main/resources/META-INF/satoken/cn.dev33.satoken.plugin.SaTokenPlugin b/sa-token-plugin/sa-token-ehcache/src/main/resources/META-INF/satoken/cn.dev33.satoken.plugin.SaTokenPlugin new file mode 100644 index 000000000..ae9d868e6 --- /dev/null +++ b/sa-token-plugin/sa-token-ehcache/src/main/resources/META-INF/satoken/cn.dev33.satoken.plugin.SaTokenPlugin @@ -0,0 +1 @@ +n.dev33.satoken.plugin.SaTokenPluginForEhcache \ No newline at end of file From 6919ea46a2a39d47a7073a7460cb5c50584701d7 Mon Sep 17 00:00:00 2001 From: sanyang176 Date: Wed, 25 Jun 2025 22:04:09 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0demo=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/pj/SaTokenDemoApplication.java | 4 ++-- .../src/main/java/com/pj/test/LoginController.java | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/SaTokenDemoApplication.java b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/SaTokenDemoApplication.java index 105a522d8..dacc4d46b 100644 --- a/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/SaTokenDemoApplication.java +++ b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/SaTokenDemoApplication.java @@ -5,8 +5,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * Sa-Token 整合 Caffeine 示例 - * @author click33 + * Sa-Token 整合 Ehcache 示例 + * @author sanyang176 * */ @SpringBootApplication diff --git a/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/test/LoginController.java b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/test/LoginController.java index cfd4e82b0..013f804b8 100644 --- a/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/test/LoginController.java +++ b/sa-token-demo/sa-token-demo-ehcache/src/main/java/com/pj/test/LoginController.java @@ -6,6 +6,11 @@ import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.util.SaResult; +/** + * 登录测试 + * @author sanyang176 + * + */ @RestController @RequestMapping("/acc/") public class LoginController {