支持redis单机或集群缓存
This commit is contained in:
parent
cf211fa19c
commit
86dd0b3be6
|
|
@ -23,6 +23,12 @@
|
|||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 支持redis缓存 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-boot-devtools -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
package com.ruoyi.web.core.config;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.ehcache.EhCacheCacheManager;
|
||||
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
|
||||
@EnableCaching
|
||||
@Configuration
|
||||
public class CacheConfig {
|
||||
@Autowired(required = false)
|
||||
RedisConnectionFactory redisConnectionFactory;
|
||||
//默认超时设置1小时
|
||||
@Value("${spring.redis.defaultExpiration:3600}")
|
||||
Duration defaultExpiration;
|
||||
//自定义部分缓存的超时
|
||||
@Value("${spring.redis.expires}")
|
||||
String expires = "{}";
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager() {
|
||||
if (redisConnectionFactory != null) {
|
||||
try {
|
||||
//配置有redis standalone或cluster,并且能正常连接时才启用redis缓存
|
||||
redisConnectionFactory.getConnection().ping();
|
||||
System.err.println("using redis cache manager");
|
||||
RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults
|
||||
(RedisCacheConfiguration.defaultCacheConfig().entryTtl(defaultExpiration))
|
||||
.withInitialCacheConfigurations(Maps.transformValues(JSON.parseObject(expires, Map.class), d ->
|
||||
RedisCacheConfiguration
|
||||
.defaultCacheConfig().entryTtl(Duration.ofSeconds(Long.valueOf(d.toString())))))
|
||||
.transactionAware().build();
|
||||
return redisCacheManager;
|
||||
} catch (Exception e) {
|
||||
System.err.println("fail to connect to redis");
|
||||
}
|
||||
}
|
||||
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
|
||||
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("classpath:ehcache/ehcache-shiro.xml"));
|
||||
ehCacheManagerFactoryBean.setShared(true);
|
||||
return new EhCacheCacheManager(ehCacheManagerFactoryBean.getObject()) {
|
||||
@Override
|
||||
protected Cache getMissingCache(String name) {
|
||||
Cache cache = super.getMissingCache(name);
|
||||
if (cache == null) {
|
||||
//使用default配置克隆缓存
|
||||
getCacheManager().addCacheIfAbsent(name);
|
||||
cache = super.getCache(name);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -69,6 +69,22 @@ spring:
|
|||
restart:
|
||||
# 热部署开关
|
||||
enabled: true
|
||||
# redis配置
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
password:
|
||||
timeout: 1500ms
|
||||
# redis连接池配置
|
||||
jedis:
|
||||
pool:
|
||||
min-idle: 1
|
||||
# redis集群配置,逗号分隔多个host:port
|
||||
# cluster:
|
||||
# nodes: 127.0.0.1:6381,127.0.0.1:6382
|
||||
# 默认缓存超时1小时,启动时可初始化多个缓存并指定超时N秒
|
||||
defaultExpiration: 1h
|
||||
expires: '{ "loginRecordCache": "600" }'
|
||||
|
||||
# MyBatis
|
||||
mybatis:
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import java.io.InputStream;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import com.ruoyi.framework.shiro.cache.SpringCacheManagerWrapper;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.shiro.cache.ehcache.EhCacheManager;
|
||||
import org.apache.shiro.codec.Base64;
|
||||
|
|
@ -17,8 +19,10 @@ import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
|||
import org.apache.shiro.web.mgt.CookieRememberMeManager;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.apache.shiro.web.servlet.SimpleCookie;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
|
@ -93,23 +97,27 @@ public class ShiroConfig
|
|||
@Value("${shiro.user.unauthorizedUrl}")
|
||||
private String unauthorizedUrl;
|
||||
|
||||
@Autowired(required = false)
|
||||
private CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* 缓存管理器 使用Ehcache实现
|
||||
* 缓存管理器 使用Spring CacheManager或Ehcache实现
|
||||
*/
|
||||
@Bean
|
||||
public EhCacheManager getEhCacheManager()
|
||||
public org.apache.shiro.cache.CacheManager getEhCacheManager()
|
||||
{
|
||||
net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruoyi");
|
||||
EhCacheManager em = new EhCacheManager();
|
||||
if (StringUtils.isNull(cacheManager))
|
||||
{
|
||||
em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
|
||||
return em;
|
||||
}
|
||||
else
|
||||
{
|
||||
em.setCacheManager(cacheManager);
|
||||
return em;
|
||||
if(cacheManager != null){
|
||||
return new SpringCacheManagerWrapper(cacheManager);
|
||||
}else {
|
||||
net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruoyi");
|
||||
EhCacheManager em = new EhCacheManager();
|
||||
if (StringUtils.isNull(cacheManager)) {
|
||||
em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
|
||||
return em;
|
||||
} else {
|
||||
em.setCacheManager(cacheManager);
|
||||
return em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +150,7 @@ public class ShiroConfig
|
|||
* 自定义Realm
|
||||
*/
|
||||
@Bean
|
||||
public UserRealm userRealm(EhCacheManager cacheManager)
|
||||
public UserRealm userRealm(org.apache.shiro.cache.CacheManager cacheManager)
|
||||
{
|
||||
UserRealm userRealm = new UserRealm();
|
||||
userRealm.setCacheManager(cacheManager);
|
||||
|
|
|
|||
22
ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/cache/SpringCacheManagerWrapper.java
vendored
Normal file
22
ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/cache/SpringCacheManagerWrapper.java
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package com.ruoyi.framework.shiro.cache;
|
||||
|
||||
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheException;
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
|
||||
/** 包装Spring CacheManager为Shiro CacheManager */
|
||||
public class SpringCacheManagerWrapper implements CacheManager {
|
||||
|
||||
private org.springframework.cache.CacheManager cacheManager;
|
||||
|
||||
public SpringCacheManagerWrapper(org.springframework.cache.CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
|
||||
org.springframework.cache.Cache springCache = cacheManager.getCache(name);
|
||||
return new SpringCacheWrapper(springCache);
|
||||
}
|
||||
}
|
||||
106
ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/cache/SpringCacheWrapper.java
vendored
Normal file
106
ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/cache/SpringCacheWrapper.java
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
package com.ruoyi.framework.shiro.cache;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheException;
|
||||
import org.apache.shiro.util.CollectionUtils;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/** 包装Spring Cache为Shiro Cache */
|
||||
public class SpringCacheWrapper implements Cache {
|
||||
private org.springframework.cache.Cache springCache;
|
||||
private boolean isEhcache;
|
||||
private Set<Object> keys;
|
||||
|
||||
SpringCacheWrapper(org.springframework.cache.Cache springCache) {
|
||||
this.springCache = springCache;
|
||||
this.isEhcache = springCache.getNativeCache() instanceof Ehcache;
|
||||
if (!this.isEhcache) {
|
||||
keys = new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object key) throws CacheException {
|
||||
Object value = springCache.get(isEhcache ? key : key.toString());
|
||||
if (value instanceof SimpleValueWrapper) {
|
||||
return ((SimpleValueWrapper) value).get();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object put(Object key, Object value) throws CacheException {
|
||||
springCache.put(isEhcache ? key : key.toString(), value);
|
||||
if (!isEhcache) {
|
||||
keys.add(key.toString());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove(Object key) throws CacheException {
|
||||
springCache.evict(isEhcache ? key : key.toString());
|
||||
if (!isEhcache) {
|
||||
keys.remove(key.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() throws CacheException {
|
||||
springCache.clear();
|
||||
if (!isEhcache) {
|
||||
keys.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if (isEhcache) {
|
||||
Ehcache ehcache = (Ehcache) springCache.getNativeCache();
|
||||
return ehcache.getSize();
|
||||
} else {
|
||||
return keys.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set keys() {
|
||||
if (isEhcache) {
|
||||
Ehcache ehcache = (Ehcache) springCache.getNativeCache();
|
||||
return new HashSet<Object>(ehcache.getKeys());
|
||||
} else {
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection values() {
|
||||
if (isEhcache) {
|
||||
Ehcache ehcache = (Ehcache) springCache.getNativeCache();
|
||||
List keys = ehcache.getKeys();
|
||||
if (!CollectionUtils.isEmpty(keys)) {
|
||||
List<Object> values = new ArrayList<>(keys.size());
|
||||
for (Object key : keys) {
|
||||
Object value = get(key);
|
||||
if (value != null) {
|
||||
values.add(value);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(values);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} else {
|
||||
List<Object> values = new ArrayList<>(keys.size());
|
||||
for (Object key : keys) {
|
||||
Object value = get(key);
|
||||
values.add(value);
|
||||
}
|
||||
return Collections.unmodifiableCollection(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,6 +92,8 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
|
|||
}
|
||||
// 更新上次同步数据库时间
|
||||
onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
|
||||
// 保存数据更新到缓存,避免每次都同步到数据库
|
||||
cache(onlineSession, onlineSession.getId());
|
||||
// 更新完后 重置标识
|
||||
if (onlineSession.isAttributeChanged())
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue