Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
提交反馈
为 GitLab 提交贡献
登录
切换导航
iBiz4j Spring R7
项目
项目
详情
动态
版本
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
iBiz-R7后台标准模板
iBiz4j Spring R7
提交
9d3aa398
提交
9d3aa398
编写于
5月 08, 2020
作者:
zhouweidong
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
补充缓存开关
上级
575fcb58
变更
10
显示空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
356 行增加
和
232 行删除
+356
-232
CaffeineCacheConfig.java.ftl
...ava/%SYS_PKGPATH%/util/cache/CaffeineCacheConfig.java.ftl
+43
-0
RedisCacheConfig.java.ftl
...n/java/%SYS_PKGPATH%/util/cache/RedisCacheConfig.java.ftl
+32
-40
CusRedisCache.java.ftl
...ava/%SYS_PKGPATH%/util/cache/cache/CusRedisCache.java.ftl
+19
-0
LayeringCache.java.ftl
...ava/%SYS_PKGPATH%/util/cache/cache/LayeringCache.java.ftl
+46
-74
CaffeineCacheManager.java.ftl
...TH%/util/cache/cacheManager/CaffeineCacheManager.java.ftl
+102
-0
LayeringCacheManager.java.ftl
...TH%/util/cache/cacheManager/LayeringCacheManager.java.ftl
+102
-0
RedisMessageListener.java.ftl
...KGPATH%/util/cache/listener/RedisMessageListener.java.ftl
+7
-4
FirstCacheSetting.java.ftl
...YS_PKGPATH%/util/cache/setting/FirstCacheSetting.java.ftl
+0
-23
SecondaryCacheSetting.java.ftl
...KGPATH%/util/cache/setting/SecondaryCacheSetting.java.ftl
+0
-87
application-sys.yml.ftl
SLN/%PUBPRJ%-util/src/main/resources/application-sys.yml.ftl
+5
-4
未找到文件。
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/CaffeineCacheConfig.java.ftl
0 → 100644
浏览文件 @
9d3aa398
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
;
import
com
.
github
.
benmanes
.
caffeine
.
cache
.
CaffeineSpec
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
cacheManager
.
CaffeineCacheManager
;
import
org
.
springframework
.
beans
.
factory
.
annotation
.
Autowired
;
import
org
.
springframework
.
boot
.
autoconfigure
.
cache
.
CacheProperties
;
import
org
.
springframework
.
boot
.
autoconfigure
.
condition
.
ConditionalOnProperty
;
import
org
.
springframework
.
boot
.
context
.
properties
.
EnableConfigurationProperties
;
import
org
.
springframework
.
cache
.
CacheManager
;
import
org
.
springframework
.
cache
.
annotation
.
EnableCaching
;
import
org
.
springframework
.
context
.
annotation
.
Bean
;
import
org
.
springframework
.
context
.
annotation
.
Configuration
;
import
org
.
springframework
.
context
.
annotation
.
Primary
;
import
org
.
springframework
.
util
.
StringUtils
;
/**
*
Caffeine
缓存配置类
*/
@
EnableCaching
@
Configuration
@
EnableConfigurationProperties
(
CacheProperties
.
class
)
@
ConditionalOnProperty
(
"ibiz.enableCaffeineCache"
)
public
class
CaffeineCacheConfig
{
@
Autowired
private
CacheProperties
cacheProperties
;
@
Autowired
private
CaffeineCacheManager
caffeineCacheManager
;
@
Bean
@
Primary
public
CacheManager
cacheManager
()
{
String
specification
=
cacheProperties
.
getCaffeine
().
getSpec
();
if
(
StringUtils
.
hasText
(
specification
))
{
caffeineCacheManager
.
setCaffeineSpec
(
CaffeineSpec
.
parse
(
specification
));
}
return
caffeineCacheManager
;
}
}
\ No newline at end of file
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/CacheConfig.java.ftl
→
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/
Redis
CacheConfig.java.ftl
浏览文件 @
9d3aa398
...
...
@@ -8,15 +8,16 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect;
import
com
.
fasterxml
.
jackson
.
annotation
.
PropertyAccessor
;
import
com
.
fasterxml
.
jackson
.
databind
.
ObjectMapper
;
import
com
.
github
.
benmanes
.
caffeine
.
cache
.
CaffeineSpec
;
import
${
pub
.
getPKGCodeName
()}.
util
.
enums
.
RedisChannelTopic
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
layering
.
LayeringCacheManager
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
cacheManager
.
LayeringCacheManager
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
redis
.
KryoRedisSerializer
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
redis
.
StringRedisSerializer
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
setting
.
FirstCacheSetting
;
import
${
pub
.
getPKGCodeName
()}.
util
.
enums
.
RedisChannelTopic
;
import
org
.
springframework
.
beans
.
factory
.
annotation
.
Autowired
;
import
org
.
springframework
.
boot
.
autoconfigure
.
cache
.
CacheProperties
;
import
org
.
springframework
.
boot
.
autoconfigure
.
condition
.
ConditionalOnProperty
;
import
org
.
springframework
.
boot
.
context
.
properties
.
EnableConfigurationProperties
;
import
org
.
springframework
.
cache
.
CacheManager
;
import
org
.
springframework
.
cache
.
annotation
.
EnableCaching
;
import
org
.
springframework
.
context
.
annotation
.
Bean
;
import
org
.
springframework
.
context
.
annotation
.
Configuration
;
import
org
.
springframework
.
context
.
annotation
.
Primary
;
...
...
@@ -24,16 +25,11 @@ import org.springframework.data.redis.cache.RedisCacheConfiguration;
import
org
.
springframework
.
data
.
redis
.
cache
.
RedisCacheManager
;
import
org
.
springframework
.
data
.
redis
.
cache
.
RedisCacheWriter
;
import
org
.
springframework
.
data
.
redis
.
connection
.
RedisConnectionFactory
;
import
org
.
springframework
.
cache
.
annotation
.
EnableCaching
;
import
org
.
springframework
.
context
.
annotation
.
Profile
;
import
org
.
springframework
.
data
.
redis
.
core
.
RedisTemplate
;
import
org
.
springframework
.
data
.
redis
.
listener
.
RedisMessageListenerContainer
;
import
org
.
springframework
.
data
.
redis
.
listener
.
adapter
.
MessageListenerAdapter
;
import
org
.
springframework
.
data
.
redis
.
serializer
.
Jackson2JsonRedisSerializer
;
import
org
.
springframework
.
boot
.
autoconfigure
.
condition
.
ConditionalOnProperty
;
import
org
.
springframework
.
util
.
StringUtils
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
Map
;
/**
*
缓存配置类
...
...
@@ -43,9 +39,17 @@ import java.util.Map;
@
EnableCaching
@
Configuration
@
EnableConfigurationProperties
(
CacheProperties
.
class
)
@
ConditionalOnProperty
(
"ibiz.enableCache"
)
public
class
CacheConfig
{
@
ConditionalOnProperty
(
"ibiz.enable
Redis
Cache"
)
public
class
Redis
CacheConfig
{
@
Autowired
private
RedisCacheWriter
redisCacheWriter
;
@
Autowired
private
RedisCacheConfiguration
configuration
;
@
Autowired
LayeringCacheManager
layeringCacheManager
;
@
Autowired
private
CacheProperties
cacheProperties
;
@
Bean
public
RedisCacheManager
redisCacheManager
(
RedisConnectionFactory
connectionFactory
)
{
return
RedisCacheManager
.
create
(
connectionFactory
);
...
...
@@ -57,12 +61,6 @@ public class CacheConfig {
return
redisCacheWriter
;
}
@
Autowired
private
RedisCacheWriter
redisCacheWriter
;
@
Autowired
private
RedisCacheConfiguration
configuration
;
/**
*
重写
Redis
序列化方式,使用
Json
方式
:
*
当我们的数据存储到
Redis
的时候,我们的键(
key
)和值(
value
)都是通过
Spring
提供的
Serializer
序列化到数据库的。
RedisTemplate
默认使用的是
JdkSerializationRedisSerializer
,
StringRedisTemplate
默认使用的是
StringRedisSerializer
。
...
...
@@ -92,41 +90,35 @@ public class CacheConfig {
return
redisTemplate
;
}
@
Bean
@
Primary
public
CacheManager
cacheManager
(
RedisTemplate
<
String
,
Object
>
redisTemplate
)
{
LayeringCacheManager
layeringCacheManager
=
new
LayeringCacheManager
(
redisTemplate
);
setFirstCacheConfig
(
layeringCacheManager
);//
Caffeine
缓存设置
layeringCacheManager
.
setAllowNullValues
(
true
);
//
允许存
null
,防止缓存击穿
public
CacheManager
cacheManager
()
{
setCaffeineCacheConfig
(
layeringCacheManager
);//
Caffeine
缓存设置
layeringCacheManager
.
setRedisCacheWriter
(
redisCacheWriter
);
layeringCacheManager
.
setRedisConfiguration
(
configuration
);
return
layeringCacheManager
;
}
@
Autowired
private
CacheProperties
cacheProperties
;
private
void
setFirstCacheConfig
(
LayeringCacheManager
layeringCacheManager
)
{
private
void
setCaffeineCacheConfig
(
LayeringCacheManager
layeringCacheManager
)
{
String
specification
=
cacheProperties
.
getCaffeine
().
getSpec
();
if
(
StringUtils
.
hasText
(
specification
))
{
layeringCacheManager
.
setCaffeineSpec
(
CaffeineSpec
.
parse
(
specification
));
}
Map
<
String
,
FirstCacheSetting
>
firstCacheSettings
=
new
HashMap
<>();
layeringCacheManager
.
setFirstCacheSettings
(
firstCacheSettings
);
}
<#--/**-->
<#--*
监听
redis
指定频道
-->
<#--*
@
param
redisConnectionFactory
-->
<#--*
@
param
messageListener
-->
<#--*
@
return
-->
<#--*/-->
<#--@
Bean
-->
<#--
RedisMessageListenerContainer
redisContainer
(
RedisConnectionFactory
redisConnectionFactory
,
MessageListenerAdapter
messageListener
)
{-->
<#--
final
RedisMessageListenerContainer
container
=
new
RedisMessageListenerContainer
();-->
<#--
container
.
setConnectionFactory
(
redisConnectionFactory
);-->
<#--
container
.
addMessageListener
(
messageListener
,
RedisChannelTopic
.
REDIS_CACHE_DELETE_TOPIC
.
getChannelTopic
());-->
<#--
container
.
addMessageListener
(
messageListener
,
RedisChannelTopic
.
REDIS_CACHE_CLEAR_TOPIC
.
getChannelTopic
());-->
<#--
return
container
;-->
<#--}-->
/**
*
监听
redis
指定频道
*
@
param
redisConnectionFactory
*
@
param
messageListener
*
@
return
*/
@
Bean
RedisMessageListenerContainer
redisContainer
(
RedisConnectionFactory
redisConnectionFactory
,
MessageListenerAdapter
messageListener
)
{
final
RedisMessageListenerContainer
container
=
new
RedisMessageListenerContainer
();
container
.
setConnectionFactory
(
redisConnectionFactory
);
container
.
addMessageListener
(
messageListener
,
RedisChannelTopic
.
REDIS_CACHE_DELETE_TOPIC
.
getChannelTopic
());
container
.
addMessageListener
(
messageListener
,
RedisChannelTopic
.
REDIS_CACHE_CLEAR_TOPIC
.
getChannelTopic
());
return
container
;
}
}
\ No newline at end of file
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/cache/CusRedisCache.java.ftl
0 → 100644
浏览文件 @
9d3aa398
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
cache
;
import
org
.
springframework
.
data
.
redis
.
cache
.
RedisCache
;
import
org
.
springframework
.
data
.
redis
.
cache
.
RedisCacheConfiguration
;
import
org
.
springframework
.
data
.
redis
.
cache
.
RedisCacheWriter
;
/**
*
自定义的
redis
缓存
*/
public
class
CusRedisCache
extends
RedisCache
{
public
CusRedisCache
(
String
name
,
RedisCacheWriter
redisCacheWriter
,
RedisCacheConfiguration
configuration
)
{
super
(
name
,
redisCacheWriter
,
configuration
);
}
}
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/
layering
/LayeringCache.java.ftl
→
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/
cache
/LayeringCache.java.ftl
浏览文件 @
9d3aa398
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
layering
;
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
cache
;
import
${
pub
.
getPKGCodeName
()}.
util
.
enums
.
RedisChannelTopic
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
listener
.
RedisPublisher
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
redis
.
CustomizedRedisCache
;
import
${
pub
.
getPKGCodeName
()}.
util
.
enums
.
RedisChannelTopic
;
import
org
.
slf4j
.
Logger
;
import
org
.
slf4j
.
LoggerFactory
;
import
org
.
springframework
.
cache
.
caffeine
.
CaffeineCache
;
...
...
@@ -18,55 +17,41 @@ import org.springframework.data.redis.core.RedisOperations;
import
java
.
util
.
HashMap
;
import
java
.
util
.
Map
;
import
java
.
util
.
concurrent
.
Callable
;
/**
*
缓存分层类
*
1
级缓存为
caffeine
*
2
级缓存为
redis
*/
public
class
LayeringCache
extends
AbstractValueAdaptingCache
{
Logger
logger
=
LoggerFactory
.
getLogger
(
LayeringCache
.
class
);
Logger
logger
=
LoggerFactory
.
getLogger
(
LayeringCache
.
class
);
/**
*
缓存的名称
*/
private
final
String
name
;
/**
*
是否使用一级缓存
*/
private
boolean
usedFirstCache
=
true
;
/**
*
redi
缓存
*
redi
s
缓存
*/
private
RedisCache
redisCache
;
/**
*
Caffeine
缓存
*/
private
final
CaffeineCache
caffeineCache
;
RedisOperations
<?
extends
Object
,
?
extends
Object
>
redisOperations
;
/**
*
@
param
name
缓存名称
*
@
param
allowNullValues
是否允许存
NULL
,默认是
false
*
@
param
usedFirstCache
是否使用一级缓存,默认是
true
*
@
param
caffeineCache
Caffeine
缓存
*
redis
消息发布
*/
public
LayeringCache
(
String
name
,
boolean
allowNullValues
,
RedisOperations
redisOperations
,
boolean
usedFirstCache
,
com
.
github
.
benmanes
.
caffeine
.
cache
.
Cache
<
Object
,
Object
>
caffeineCache
,
RedisOperations
<?
extends
Object
,
?
extends
Object
>
redisOperations
;
public
LayeringCache
(
String
name
,
RedisOperations
redisOperations
,
com
.
github
.
benmanes
.
caffeine
.
cache
.
Cache
<
Object
,
Object
>
caffeineCache
,
RedisCacheWriter
redisCacheWriter
,
RedisCacheConfiguration
configuration
)
{
super
(
allowNullValues
);
super
(
true
);
this
.
name
=
name
;
this
.
usedFirstCache
=
usedFirstCache
;
this
.
redisCache
=
new
CustomizedRedisCache
(
name
,
redisCacheWriter
,
configuration
);
this
.
caffeineCache
=
new
CaffeineCache
(
name
,
caffeineCache
,
allowNullValues
);
this
.
redisCache
=
new
CusRedisCache
(
name
,
redisCacheWriter
,
configuration
);
this
.
caffeineCache
=
new
CaffeineCache
(
name
,
caffeineCache
,
true
);
this
.
redisOperations
=
redisOperations
;
}
public
CaffeineCache
getFirstCache
()
{
return
this
.
caffeineCache
;
}
@
Override
public
String
getName
()
{
return
this
.
name
;
...
...
@@ -79,13 +64,9 @@ public class LayeringCache extends AbstractValueAdaptingCache {
@
Override
public
ValueWrapper
get
(
Object
key
)
{
ValueWrapper
wrapper
=
null
;
if
(
usedFirstCache
)
{
//
查询一级缓存
wrapper
=
caffeineCache
.
get
(
key
);
ValueWrapper
wrapper
=
caffeineCache
.
get
(
key
);
logger
.
debug
(
"查询一级缓存 key:{},value:{}"
,
key
,
wrapper
);
}
if
(
wrapper
==
null
)
{
//
查询二级缓存
wrapper
=
redisCache
.
get
(
key
);
...
...
@@ -97,12 +78,9 @@ public class LayeringCache extends AbstractValueAdaptingCache {
@
Override
public
<
T
>
T
get
(
Object
key
,
Class
<
T
>
type
)
{
T
value
=
null
;
if
(
usedFirstCache
)
{
//
查询一级缓存
value
=
caffeineCache
.
get
(
key
,
type
);
T
value
=
caffeineCache
.
get
(
key
,
type
);
logger
.
debug
(
"查询一级缓存 key:{}"
,
key
);
}
if
(
value
==
null
)
{
//
查询二级缓存
value
=
redisCache
.
get
(
key
,
type
);
...
...
@@ -115,15 +93,12 @@ public class LayeringCache extends AbstractValueAdaptingCache {
@
SuppressWarnings
(
"unchecked"
)
@
Override
public
<
T
>
T
get
(
Object
key
,
Callable
<
T
>
valueLoader
)
{
T
value
=
null
;
if
(
usedFirstCache
)
{
//
查询一级缓存
,
如果一级缓存没有值则调用
getForSecondaryCache
(
k
,
valueLoader
)
查询二级缓存
value
=
(
T
)
caffeineCache
.
getNativeCache
().
get
(
key
,
k
->
getForSecondary
Cache
(
k
,
valueLoader
));
}
else
{
T
value
=
(
T
)
caffeineCache
.
getNativeCache
().
get
(
key
,
k
->
getSecond
Cache
(
k
,
valueLoader
));
if
(
value
==
null
)
{
//
直接查询二级缓存
value
=
(
T
)
get
ForSecondary
Cache
(
key
,
valueLoader
);
value
=
(
T
)
get
Second
Cache
(
key
,
valueLoader
);
}
if
(
value
instanceof
NullValue
)
{
return
null
;
}
...
...
@@ -132,53 +107,42 @@ public class LayeringCache extends AbstractValueAdaptingCache {
@
Override
public
void
put
(
Object
key
,
Object
value
)
{
if
(
usedFirstCache
)
{
caffeineCache
.
put
(
key
,
value
);
}
redisCache
.
put
(
key
,
value
);
}
@
Override
public
ValueWrapper
putIfAbsent
(
Object
key
,
Object
value
)
{
if
(
usedFirstCache
)
{
caffeineCache
.
putIfAbsent
(
key
,
value
);
}
return
redisCache
.
putIfAbsent
(
key
,
value
);
}
@
Override
public
void
evict
(
Object
key
)
{
redisCache
.
evict
(
key
);
//
清除
redis
中的二级缓存
if
(
usedFirstCache
)
{
caffeineCache
.
evict
(
key
);//
清除本机一级缓存
Map
<
String
,
Object
>
message
=
new
HashMap
<>();
message
.
put
(
"cacheName"
,
name
);
message
.
put
(
"key"
,
key
);
RedisPublisher
redisPublisher
=
new
RedisPublisher
(
redisOperations
,
RedisChannelTopic
.
REDIS_CACHE_DELETE_TOPIC
.
getChannelTopic
());//
创建
redis
发布者
redisPublisher
.
publisher
(
message
);//
发布消息,清除其它集群机器中的一级缓存
}
logger
.
debug
(
String
.
format
(
"清除二级缓存数据[%s]"
,
key
));
}
@
Override
public
void
clear
()
{
redisCache
.
clear
();
//
清除
redis
中的二级缓存
if
(
usedFirstCache
)
{
caffeineCache
.
clear
();//
清除本机一级缓存
Map
<
String
,
Object
>
message
=
new
HashMap
<>();
message
.
put
(
"cacheName"
,
name
);
RedisPublisher
redisPublisher
=
new
RedisPublisher
(
redisOperations
,
RedisChannelTopic
.
REDIS_CACHE_CLEAR_TOPIC
.
getChannelTopic
());//
创建
redis
发布者
redisPublisher
.
publisher
(
message
);//
发布消息,清除其它集群机器中的一级缓存
}
}
@
Override
protected
Object
lookup
(
Object
key
)
{
Object
value
=
null
;
if
(
usedFirstCache
)
{
value
=
caffeineCache
.
get
(
key
);
Object
value
=
caffeineCache
.
get
(
key
);
logger
.
debug
(
"查询一级缓存 key:{}"
,
key
);
}
if
(
value
==
null
)
{
value
=
redisCache
.
get
(
key
);
logger
.
debug
(
"查询二级缓存 key:{}"
,
key
);
...
...
@@ -192,9 +156,17 @@ public class LayeringCache extends AbstractValueAdaptingCache {
*
@
param
valueLoader
*
@
return
*/
private
<
T
>
Object
get
ForSecondary
Cache
(
Object
key
,
Callable
<
T
>
valueLoader
)
{
private
<
T
>
Object
get
Second
Cache
(
Object
key
,
Callable
<
T
>
valueLoader
)
{
T
value
=
redisCache
.
get
(
key
,
valueLoader
);
logger
.
debug
(
"查询二级缓存 key:{}"
,
key
);
return
toStoreValue
(
value
);
}
/**
*
获取
caffeine
缓存
*
@
return
*/
public
CaffeineCache
getFirstCache
()
{
return
this
.
caffeineCache
;
}
}
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/cacheManager/CaffeineCacheManager.java.ftl
0 → 100644
浏览文件 @
9d3aa398
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
cacheManager
;
import
com
.
github
.
benmanes
.
caffeine
.
cache
.
Caffeine
;
import
com
.
github
.
benmanes
.
caffeine
.
cache
.
CaffeineSpec
;
import
lombok
.
Data
;
import
org
.
springframework
.
boot
.
autoconfigure
.
condition
.
ConditionalOnProperty
;
import
org
.
springframework
.
cache
.
Cache
;
import
org
.
springframework
.
cache
.
CacheManager
;
import
org
.
springframework
.
cache
.
caffeine
.
CaffeineCache
;
import
org
.
springframework
.
stereotype
.
Component
;
import
org
.
springframework
.
util
.
ObjectUtils
;
import
java
.
util
.
Collection
;
import
java
.
util
.
Collections
;
import
java
.
util
.
Map
;
import
java
.
util
.
concurrent
.
ConcurrentHashMap
;
import
java
.
util
.
concurrent
.
ConcurrentMap
;
import
java
.
util
.
concurrent
.
TimeUnit
;
/**
*
Caffeine
本地缓存
*/
@
Data
@
Component
@
ConditionalOnProperty
(
"ibiz.enableCaffeineCache"
)
public
class
CaffeineCacheManager
implements
CacheManager
{
private
static
final
int
DEFAULT_EXPIRE_AFTER_WRITE
=
1
;
private
static
final
int
DEFAULT_INITIAL_CAPACITY
=
5
;
private
static
final
int
DEFAULT_MAXIMUM_SIZE
=
1
_000
;
private
final
ConcurrentMap
<
String
,
Cache
>
cacheMap
=
new
ConcurrentHashMap
<
String
,
Cache
>(
16
);
/**
*
缓存默认设置
*/
private
Caffeine
<
Object
,
Object
>
cacheBuilder
=
Caffeine
.
newBuilder
()
.
expireAfterAccess
(
DEFAULT_EXPIRE_AFTER_WRITE
,
TimeUnit
.
HOURS
)
.
initialCapacity
(
DEFAULT_INITIAL_CAPACITY
)
.
maximumSize
(
DEFAULT_MAXIMUM_SIZE
);
/**
*
获取缓存对象
*
@
param
name
*
@
return
*/
@
Override
public
Cache
getCache
(
String
name
)
{
Cache
cache
=
this
.
cacheMap
.
get
(
name
);
if
(
cache
==
null
)
{
synchronized
(
this
.
cacheMap
)
{
cache
=
this
.
cacheMap
.
get
(
name
);
if
(
cache
==
null
)
{
cache
=
createCache
(
name
);
this
.
cacheMap
.
put
(
name
,
cache
);
}
}
}
return
cache
;
}
/**
*
获取缓存名
*
@
return
*/
@
Override
public
Collection
<
String
>
getCacheNames
()
{
return
Collections
.
unmodifiableSet
(
this
.
cacheMap
.
keySet
());
}
/**
*
创建缓存
*
@
param
name
*
@
return
*/
protected
Cache
createCache
(
String
name
)
{
return
new
CaffeineCache
(
name
,
this
.
cacheBuilder
.
build
(),
true
);
}
/**
*
缓存配置
[
缓存容量大小、时长等
]
*
@
param
caffeineSpec
*/
public
void
setCaffeineSpec
(
CaffeineSpec
caffeineSpec
)
{
Caffeine
<
Object
,
Object
>
cacheBuilder
=
Caffeine
.
from
(
caffeineSpec
);
if
(
!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) {
this
.
cacheBuilder
=
cacheBuilder
;
refreshKnownCaches
();
}
}
/**
*
使用该
CacheManager
的当前状态重新创建已知的缓存。
*/
private
void
refreshKnownCaches
()
{
for
(
Map
.
Entry
<
String
,
Cache
>
entry
:
this
.
cacheMap
.
entrySet
())
{
entry
.
setValue
(
createCache
(
entry
.
getKey
()));
}
}
}
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/
layering
/LayeringCacheManager.java.ftl
→
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/
cacheManager
/LayeringCacheManager.java.ftl
浏览文件 @
9d3aa398
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
layering
;
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
cacheManager
;
import
com
.
github
.
benmanes
.
caffeine
.
cache
.
Caffeine
;
import
com
.
github
.
benmanes
.
caffeine
.
cache
.
CaffeineSpec
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
setting
.
FirstCacheSetting
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
setting
.
SecondaryCacheSetting
;
import
lombok
.
Data
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
cache
.
LayeringCache
;
import
org
.
springframework
.
boot
.
autoconfigure
.
condition
.
ConditionalOnProperty
;
import
org
.
springframework
.
cache
.
Cache
;
import
org
.
springframework
.
cache
.
CacheManager
;
import
org
.
springframework
.
data
.
redis
.
cache
.
RedisCacheConfiguration
;
import
org
.
springframework
.
data
.
redis
.
cache
.
RedisCacheWriter
;
import
org
.
springframework
.
data
.
redis
.
core
.
RedisOperations
;
import
org
.
springframework
.
data
.
redis
.
core
.
RedisTemplate
;
import
org
.
springframework
.
util
.
CollectionUtils
;
import
org
.
springframework
.
stereotype
.
Component
;
import
org
.
springframework
.
util
.
ObjectUtils
;
import
java
.
util
.
Collection
;
import
java
.
util
.
Collections
;
...
...
@@ -22,7 +22,6 @@ import java.util.Map;
import
java
.
util
.
concurrent
.
ConcurrentHashMap
;
import
java
.
util
.
concurrent
.
ConcurrentMap
;
import
java
.
util
.
concurrent
.
TimeUnit
;
import
org
.
springframework
.
util
.
StringUtils
;
/**
*
缓存分层类
...
...
@@ -30,40 +29,20 @@ import org.springframework.util.StringUtils;
*
2
级缓存为
redis
*/
@
Data
@
Component
@
ConditionalOnProperty
(
"ibiz.enableRedisCache"
)
public
class
LayeringCacheManager
implements
CacheManager
{
static
final
int
DEFAULT_EXPIRE_AFTER_WRITE
=
2
;
static
final
int
DEFAULT_INITIAL_CAPACITY
=
5
;
static
final
int
DEFAULT_MAXIMUM_SIZE
=
1
_000
;
private
final
ConcurrentMap
<
String
,
Cache
>
cacheMap
=
new
ConcurrentHashMap
<
String
,
Cache
>(
16
);
/**
*
一级缓存配置
*/
private
Map
<
String
,
FirstCacheSetting
>
firstCacheSettings
=
null
;
/**
*
二级缓存配置
*/
private
Map
<
String
,
SecondaryCacheSetting
>
secondaryCacheSettings
=
null
;
private
static
final
int
DEFAULT_EXPIRE_AFTER_WRITE
=
1
;
private
static
final
int
DEFAULT_INITIAL_CAPACITY
=
5
;
private
static
final
int
DEFAULT_MAXIMUM_SIZE
=
1
_000
;
private
final
ConcurrentMap
<
String
,
Cache
>
cacheMap
=
new
ConcurrentHashMap
<
String
,
Cache
>(
16
);
public
RedisCacheWriter
redisCacheWriter
;
public
RedisCacheConfiguration
redisConfiguration
;
public
RedisOperations
redisOperations
;
/**
*
是否允许动态创建缓存,默认是
true
*/
private
boolean
dynamic
=
true
;
/**
*
缓存值是否允许为
NULL
*/
private
boolean
allowNullValues
=
false
;
/**
*
expireAfterWrite
:
2
小时
*
initialCapacity
:
5
*
maximumSize
:
1
_000
*
缓存默认设置
*/
private
Caffeine
<
Object
,
Object
>
cacheBuilder
=
Caffeine
.
newBuilder
()
.
expireAfterAccess
(
DEFAULT_EXPIRE_AFTER_WRITE
,
TimeUnit
.
HOURS
)
...
...
@@ -82,7 +61,7 @@ public class LayeringCacheManager implements CacheManager {
@
Override
public
Cache
getCache
(
String
name
)
{
Cache
cache
=
this
.
cacheMap
.
get
(
name
);
if
(
cache
==
null
&&
this
.
dynamic
)
{
if
(
cache
==
null
)
{
synchronized
(
this
.
cacheMap
)
{
cache
=
this
.
cacheMap
.
get
(
name
);
if
(
cache
==
null
)
{
...
...
@@ -100,21 +79,11 @@ public class LayeringCacheManager implements CacheManager {
}
protected
Cache
createCache
(
String
name
)
{
return
new
LayeringCache
(
name
,
isAllowNullValues
(),
this
.
redisOperations
,
getUsedFirstCache
(
name
),
createNativeCaffeineCache
(
name
),
redisCacheWriter
,
redisConfiguration
);
return
new
LayeringCache
(
name
,
this
.
redisOperations
,
this
.
cacheBuilder
.
build
(
),
redisCacheWriter
,
redisConfiguration
);
}
/**
*
Create
a
native
Caffeine
Cache
instance
for
the
specified
cache
name
.
*
*
@
param
name
the
name
of
the
cache
*
@
return
the
native
Caffeine
Cache
instance
*/
protected
com
.
github
.
benmanes
.
caffeine
.
cache
.
Cache
<
Object
,
Object
>
createNativeCaffeineCache
(
String
name
)
{
return
getCaffeine
(
name
).
build
();
}
/**
*
使用该
CacheManager
的当前状态重新创建已知的缓存。
*
使用该
CacheManager
的当前状态重新创建已知的缓存
*/
private
void
refreshKnownCaches
()
{
for
(
Map
.
Entry
<
String
,
Cache
>
entry
:
this
.
cacheMap
.
entrySet
())
{
...
...
@@ -122,48 +91,6 @@ public class LayeringCacheManager implements CacheManager {
}
}
/**
*
设置是否允许
Cache
的值为
null
*
*
@
param
allowNullValues
*/
public
void
setAllowNullValues
(
boolean
allowNullValues
)
{
if
(
this
.
allowNullValues
!= allowNullValues) {
this
.
allowNullValues
=
allowNullValues
;
refreshKnownCaches
();
}
}
/**
*
获取是否允许
Cache
的值为
null
*
*
@
return
*/
public
boolean
isAllowNullValues
()
{
return
this
.
allowNullValues
;
}
/**
*
根据缓存名称设置一级缓存的有效时间和刷新时间,单位秒
*
*
@
param
firstCacheSettings
*/
public
void
setFirstCacheSettings
(
Map
<
String
,
FirstCacheSetting
>
firstCacheSettings
)
{
this
.
firstCacheSettings
=
(
!CollectionUtils.isEmpty(firstCacheSettings) ? new ConcurrentHashMap<>(firstCacheSettings) : null);
}
/**
*
获取是否使用一级缓存,默认是
true
*/
public
boolean
getUsedFirstCache
(
String
name
)
{
SecondaryCacheSetting
secondaryCacheSetting
=
null
;
if
(
!CollectionUtils.isEmpty(secondaryCacheSettings)) {
secondaryCacheSetting
=
secondaryCacheSettings
.
get
(
name
);
}
return
secondaryCacheSetting
!= null ? secondaryCacheSetting.getUsedFirstCache() : true;
}
public
void
setCaffeineSpec
(
CaffeineSpec
caffeineSpec
)
{
Caffeine
<
Object
,
Object
>
cacheBuilder
=
Caffeine
.
from
(
caffeineSpec
);
if
(
!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) {
...
...
@@ -171,14 +98,5 @@ public class LayeringCacheManager implements CacheManager {
refreshKnownCaches
();
}
}
private
Caffeine
<
Object
,
Object
>
getCaffeine
(
String
name
)
{
if
(
!CollectionUtils.isEmpty(firstCacheSettings)) {
FirstCacheSetting
firstCacheSetting
=
firstCacheSettings
.
get
(
name
);
if
(
firstCacheSetting
!= null && StringUtils.isEmpty(firstCacheSetting.getCacheSpecification())) {
//
根据缓存名称获取一级缓存配置
return
Caffeine
.
from
(
CaffeineSpec
.
parse
(
firstCacheSetting
.
getCacheSpecification
()));
}
}
return
this
.
cacheBuilder
;
}
}
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/listener/RedisMessageListener.java.ftl
浏览文件 @
9d3aa398
...
...
@@ -3,26 +3,29 @@ TARGET=PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
listener
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
cache
.
LayeringCache
;
import
${
pub
.
getPKGCodeName
()}.
util
.
enums
.
RedisChannelTopic
;
import
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
layering
.
LayeringCache
;
import
org
.
slf4j
.
Logger
;
import
org
.
slf4j
.
LoggerFactory
;
import
org
.
springframework
.
beans
.
factory
.
annotation
.
Autowired
;
import
org
.
springframework
.
boot
.
autoconfigure
.
condition
.
ConditionalOnProperty
;
import
org
.
springframework
.
cache
.
Cache
;
import
org
.
springframework
.
cache
.
CacheManager
;
import
org
.
springframework
.
context
.
annotation
.
Profile
;
import
org
.
springframework
.
data
.
redis
.
connection
.
Message
;
import
org
.
springframework
.
data
.
redis
.
core
.
RedisTemplate
;
import
org
.
springframework
.
data
.
redis
.
listener
.
adapter
.
MessageListenerAdapter
;
import
org
.
springframework
.
data
.
redis
.
serializer
.
RedisSerializer
;
import
org
.
springframework
.
stereotype
.
Component
;
import
org
.
springframework
.
util
.
StringUtils
;
import
java
.
util
.
Map
;
/**
*
redis
消息的订阅者
*/
@
Profile
(
"prod"
)
@
Component
@
ConditionalOnProperty
(
"ibiz.enableRedisCache"
)
public
class
RedisMessageListener
extends
MessageListenerAdapter
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
RedisPublisher
.
class
);
@
Autowired
...
...
@@ -41,7 +44,7 @@ public class RedisMessageListener extends MessageListenerAdapter {
map
=
(
Map
<
String
,
Object
>)
result
;
}
if
(
StringUtils
.
isEmpty
(
map
)||
(
!map.containsKey("cacheName"))|| (!map.containsKey("key"))){
logger
.
info
(
"解析缓存数据失败,无法获取指定值!"
);
logger
.
debug
(
"解析缓存数据失败,无法获取指定值!"
);
return
;
}
logger
.
debug
(
"redis消息订阅者接收到频道【{}】发布的消息。消息内容:{}"
,
channelTopic
.
getChannelTopicStr
(),
result
.
toString
());
...
...
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/setting/FirstCacheSetting.java.ftl
已删除
100644 → 0
浏览文件 @
575fcb58
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
setting
;
import
com
.
github
.
benmanes
.
caffeine
.
cache
.
CaffeineSpec
;
public
class
FirstCacheSetting
{
/**
*
一级缓存配置,配置项请点击这里
{@
link
CaffeineSpec
#
configure
(
String
,
String
)}
*
@
param
cacheSpecification
*/
public
FirstCacheSetting
(
String
cacheSpecification
)
{
this
.
cacheSpecification
=
cacheSpecification
;
}
private
String
cacheSpecification
;
public
String
getCacheSpecification
()
{
return
cacheSpecification
;
}
}
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/cache/setting/SecondaryCacheSetting.java.ftl
已删除
100644 → 0
浏览文件 @
575fcb58
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
cache
.
setting
;
public
class
SecondaryCacheSetting
{
/**
*
@
param
expirationSecondTime
设置
redis
缓存的有效时间,单位秒
*
@
param
preloadSecondTime
设置
redis
缓存的自动刷新时间,单位秒
*/
public
SecondaryCacheSetting
(
long
expirationSecondTime
,
long
preloadSecondTime
)
{
this
.
expirationSecondTime
=
expirationSecondTime
;
this
.
preloadSecondTime
=
preloadSecondTime
;
}
/**
*
@
param
usedFirstCache
是否启用一级缓存,默认
true
*
@
param
expirationSecondTime
设置
redis
缓存的有效时间,单位秒
*
@
param
preloadSecondTime
设置
redis
缓存的自动刷新时间,单位秒
*/
public
SecondaryCacheSetting
(
boolean
usedFirstCache
,
long
expirationSecondTime
,
long
preloadSecondTime
)
{
this
.
expirationSecondTime
=
expirationSecondTime
;
this
.
preloadSecondTime
=
preloadSecondTime
;
this
.
usedFirstCache
=
usedFirstCache
;
}
/**
*
@
param
expirationSecondTime
设置
redis
缓存的有效时间,单位秒
*
@
param
preloadSecondTime
设置
redis
缓存的自动刷新时间,单位秒
*
@
param
forceRefresh
是否使用强制刷新(走数据库),默认
false
*/
public
SecondaryCacheSetting
(
long
expirationSecondTime
,
long
preloadSecondTime
,
boolean
forceRefresh
)
{
this
.
expirationSecondTime
=
expirationSecondTime
;
this
.
preloadSecondTime
=
preloadSecondTime
;
this
.
forceRefresh
=
forceRefresh
;
}
/**
*
@
param
expirationSecondTime
设置
redis
缓存的有效时间,单位秒
*
@
param
preloadSecondTime
设置
redis
缓存的自动刷新时间,单位秒
*
@
param
usedFirstCache
是否启用一级缓存,默认
true
*
@
param
forceRefresh
是否使用强制刷新(走数据库),默认
false
*/
public
SecondaryCacheSetting
(
long
expirationSecondTime
,
long
preloadSecondTime
,
boolean
usedFirstCache
,
boolean
forceRefresh
)
{
this
.
expirationSecondTime
=
expirationSecondTime
;
this
.
preloadSecondTime
=
preloadSecondTime
;
this
.
usedFirstCache
=
usedFirstCache
;
this
.
forceRefresh
=
forceRefresh
;
}
/**
*
缓存有效时间
*/
private
long
expirationSecondTime
;
/**
*
缓存主动在失效前强制刷新缓存的时间
*
单位:秒
*/
private
long
preloadSecondTime
=
0
;
/**
*
是否使用一级缓存,默认是
true
*/
private
boolean
usedFirstCache
=
true
;
/**
*
是否使用强刷新(走数据库),默认是
false
*/
private
boolean
forceRefresh
=
false
;
public
long
getPreloadSecondTime
()
{
return
preloadSecondTime
;
}
public
long
getExpirationSecondTime
()
{
return
expirationSecondTime
;
}
public
boolean
getUsedFirstCache
()
{
return
usedFirstCache
;
}
public
boolean
getForceRefresh
()
{
return
forceRefresh
;
}
}
SLN/%PUBPRJ%-util/src/main/resources/application-sys.yml.ftl
浏览文件 @
9d3aa398
...
...
@@ -124,12 +124,13 @@ ribbon:
ReadTimeout: 60000
ConnectTimeout: 60000
#系统是否开启权限验证、是否开启缓存
<#assign enableCache="false">
#系统是否开启权限验证、是否开启缓存 [本地缓存:enableCaffeineCache=true 或 两级缓存(caffeine+redis):enableRedisCache=true]
ibiz:
enablePermissionValid: false
<#if sys.getPSSystemSetting()?? && sys.getPSSystemSetting().getDataAccCtrlArch()?? && sys.getPSSystemSetting().getDataAccCtrlArch()==1>
enableCache: true
<#else >
enableCache: false
<#assign enableCache="true">
</#if>
enableCaffeineCache: ${enableCache}
#enableRedisCache: ${enableCache}
编辑
预览
Markdown
格式
0%
请重试
or
添加新附件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
先完成此消息的编辑!
取消
想要评论请
注册
或
登录