当前位置:网站首页>Shiro customizes the cache and extends the Shiro cache module. You only need to configure the cache to realize session sharing
Shiro customizes the cache and extends the Shiro cache module. You only need to configure the cache to realize session sharing
2022-04-22 16:03:00 【a10534126】
Shiro Custom cache
Before doing Shiro When integrating , Go through various forums , about ehcache and redis Integration is too cumbersome , Trying to Shiro Abstract the cache of , Not changing Shiro Under the premise of , Configurable scheme to achieve cache , In that way, the cluster deployment can be better realized for the project .
So the following design is derived :
One 、 design scheme
1.Shiro Modification of configuration file
Let's introduce Shiro Custom cache for , When you have this idea , I looked through the documents and demo Finally found Shiro It supports custom caching , But integration is needed AbstractCacheManager To achieve
Shiro Custom cache only needs to be in Shiro Replace the original... In the configuration file of cacheManager,
I tried to use my new cacheManager
<bean id="cacheManager" class="com.cn.contiy.system.shiro.entity.SMCacheManager" />
SpringBoot Empathy , Just modify the code .
2. Self implemented cache class
When we integrate AbstractCacheManager after , We will find that in the AbstractCacheManager There is an abstract method that needs to be implemented
protected abstract Cache createCache(String s)
throws CacheException;
Obvious , The method is Shiro Of CacheManager To create a cache , therefore , We need to integrate here , This will not be realized for the time being ;
This method of creating a cache uses a return value Cache, The observation is based on org.apache.shiro.cache.Cache Interface , therefore , The point is how to use org.apache.shiro.cache.Cache Interface , The following is the journey of mind
a. Realization org.apache.shiro.cache.Cache Interface
b. Implementation class implementation createCache, And return to realize org.apache.shiro.cache.Cache Implementation class of interface
c. stay org.apache.shiro.cache.Cache Interface implementation class , Encapsulate the cache interface
d. Separate use Redis and Ehcache Implement the cache interface
e. Use the factory class to get the cache
f. Determine the caching method used by the project when the project starts
SO, The operation began :
(1) Create a common cache interface
public interface Cacher {
public void set(String key, Object value);
public Object get(String key);
public void delete(String key);
public Set<String> keys(String string);
public Set<?> getAllValue(String keyPrefix);
public Long dbSize();
}
I won't describe the method of interface , One is laziness , Second, I can understand what it is basically in English
(2)Cache factory , Toggle cache
public class CacherFactory {
/** @desc Caching tools */
public static Cacher cacher;
@SuppressWarnings("static-access")
public static void setAdpt(Object cacherAdpt) {
cacher = (Cacher) cacherAdpt;
}
}
After defining the cache factory , It's easy to use caching , It only needs CacherFactory.cacher that will do
(3)Redis Cache implementation class
@Service("redisCacher")
@SuppressWarnings({ "unchecked", "rawtypes" })
public class RedisCacher implements Cacher {
@Resource
private org.springframework.data.redis.core.RedisTemplate redisTemplate;
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
// BoundValueOperations Do some subtle operations on the saved values
// BoundValueOperations boundValueOperations =
// redisTemplate.boundValueOps(key);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
public void delete(String key) {
redisTemplate.delete(key);
}
/*
* (non-Javadoc)
*
* @see com.cn.contiy.system.cache.Cacher#keys(java.lang.String)
*/
@Override
public Set<String> keys(String key) {
return redisTemplate.keys(key + "*");
}
/*
* (non-Javadoc)
*
* @see com.cn.contiy.system.cache.Cacher#getAllValue(java.lang.String)
*/
@Override
public Set<?> getAllValue(String keyPrefix) {
Set<Object> list = new HashSet<Object>();
ValueOperations v = redisTemplate.opsForValue();
Set<String> keys = this.keys(keyPrefix);
for (String string : keys) {
list.add(v.get(string));
}
return list;
}
/*
* (non-Javadoc)
*
* @see com.cn.contiy.system.cache.Cacher#dbSize()
*/
@Override
public Long dbSize() {
return redisTemplate.getConnectionFactory().getConnection().dbSize();
}
}
RedisCacher As mentioned above , How to implement the interface , The same is true for other caches
(4) Realization org.apache.shiro.cache.Cache Interface
@Service("shiroCache")
public class ShiroCache<K, V> implements Cache<K, V> {
/**
* This is for Shiro The cache of Key Group identification , Identify in the cache with this Key It starts with Shiro The cache of
*/
private static final String KEY_PREFIX = "shiro_session:";
/*
* This clear The method is not done well , belong cacher Interface , Implemented by the cached implementation class
*
* @see org.apache.shiro.cache.Cache#clear()
*/
@Override
public void clear() throws CacheException {
Set<String> keys = CacherFactory.cacher.keys(KEY_PREFIX);
for (String string : keys) {
CacherFactory.cacher.delete(string);
}
}
private String getkey(String key) {
return KEY_PREFIX + key;
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#get(java.lang.Object)
*/
@SuppressWarnings("unchecked")
@Override
public V get(K arg0) throws CacheException {
return (V) CacherFactory.cacher.get(getkey(arg0.toString()));
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#keys()
*/
@SuppressWarnings("unchecked")
@Override
public Set<K> keys() {
return (Set<K>) CacherFactory.cacher.keys(KEY_PREFIX);
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#put(java.lang.Object, java.lang.Object)
*/
@Override
public V put(K arg0, V arg1) throws CacheException {
CacherFactory.cacher.set(getkey(arg0.toString()), arg1);
return arg1;
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#remove(java.lang.Object)
*/
@Override
public V remove(K arg0) throws CacheException {
V previous = get(arg0);
CacherFactory.cacher.delete(getkey(arg0.toString()));
return previous;
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#size()
*/
@Override
public int size() {
Long longSize = CacherFactory.cacher.dbSize();
return longSize.intValue();
}
/*
* Because there's only... In the cache Shiro Of key, This step is inevitable
*
* @see org.apache.shiro.cache.Cache#values()
*/
@SuppressWarnings("unchecked")
@Override
public Collection<V> values() {
Collection<V> v = new HashSet<>();
Set<String> keys = CacherFactory.cacher.keys(KEY_PREFIX);
for (String string : keys) {
if (CacherFactory.cacher.get(string) != null) {
v.add((V) CacherFactory.cacher.get(string));
}
}
return v;
}
}
(5) In the custom CacheManager Add custom Cache
public class SMCacheManager extends AbstractCacheManager {
@SuppressWarnings("unused")
private static final Logger logger = LoggerFactory.getLogger(SMCacheManager.class);
@SuppressWarnings("rawtypes")
@Resource
private Cache shiroCache;
/*
* (non-Javadoc)
*
* @see
* org.apache.shiro.cache.AbstractCacheManager#createCache(java.lang.String)
*/
@SuppressWarnings("rawtypes")
@Override
protected Cache createCache(String s) throws CacheException {
// I use Spring Injected , So I went straight back
return shiroCache;
}
}
(6) Set cache mode at startup
public void initCache() {
switchRedis = "OFF";
try {
switchRedis = systemSettingBiz.getSysDetail("system.redis.switch");
redisTemplate.opsForValue().get("");
} catch (Exception e) {
// TODO Auto-generated catch block
log.error("------------------------------redis Cache off , Switch to ehCacher----------------------");
switchRedis = "OFF";
}
if (switchRedis.equalsIgnoreCase("OFF")) {
log.info("---------------------- Turn on ehCacher------------------------------");
CacherFactory.setAdpt(ehCacher);
} else {
log.info("---------------------- Turn on redisCacher----------------------------");
CacherFactory.setAdpt(redisCacher);
}
}
(7) modify Shiro The configuration file
<bean id="cacheManager" class="com.cn.contiy.system.shiro.entity.SMCacheManager" />
thus , complete , The code is poorly written , Please don't blame , Just provide an idea
One of the advantages of this approach is Shiro It doesn't matter what cache you use , It can be said that Shiro The cache has been abstracted , You can say that , Even if the , Yours Shiro Using caching , How to use the database , It just needs to be realized Cacher Interface , Set the switch when the application starts , That is to say Shiro The cache of , The custom cache is more for Session Unified , For distributed systems , Personally, I think it's still very important .
PS: Virgin text , Please give me more advice , thank you !( show mercy )
版权声明
本文为[a10534126]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204221556281635.html
边栏推荐
- 生物素-4-荧光素实验注意事项
- Sed in shell script
- 2022-4-21 【webrtc应用】yangrtc/metaRTC开源库源码分析(三)
- Gdoi2022 retirement (from heaven to earth)
- 基于jedis的redis操作工具类
- 建筑业未来的发展方向:数字化工厂管理系统
- Altium designer generates PCB production files and proofing process (taking jialichuang mall as an example)
- 网站优化后如何降低阿里云国际版服务器成本
- [Kunpeng training camp] Chongqing 2022 developer competition
- Set JSON encoding
猜你喜欢
随机推荐
npm的使用
[b01lers2020]Life on Mars
企业级知识管理(KM)建设方法及过程
牛客SQL刷题记录
Small pit on the definition of two-dimensional or multi-dimensional array / slice in go language
Set JSON encoding
【无标题】
Oopmap theory
bluetoothGatt.disconnect()无效,还是保持着连接
腾讯云堡垒机开启OTP认证
Grafana series (IX): introduction to Loki, an open source cloud native logging solution
sql語句———多錶聯查
342-Leetcode 字符串中的第一个唯一字符
Servlet Foundation
Immundiagnostik IDK TurbiPEL测定分析
Greenplum【环境搭建 05】GP最新版本v6.20.3配置安装验证(内核参数+初始化参数说明)
【虹科技术分享】ntopng是如何进行攻击者和受害者检测
396.旋转函数
JSP echo
citespace安装和使用教程









