Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gk
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
micro_app
gk
Commits
d37316ac
Commit
d37316ac
authored
Jul 01, 2026
by
Administrator
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
三级缓存模版方法添加
parent
e6400610
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
143 additions
and
33 deletions
+143
-33
CacheTemplate.java
...in/java/com/dlbridge/jadp/common/cache/CacheTemplate.java
+130
-0
WebConfig.java
src/main/java/com/dlbridge/jadp/config/web/WebConfig.java
+1
-2
MicroApiController.java
...om/dlbridge/jadp/plugins/cmpt/web/MicroApiController.java
+12
-31
No files found.
src/main/java/com/dlbridge/jadp/common/cache/CacheTemplate.java
0 → 100644
View file @
d37316ac
package
com
.
dlbridge
.
jadp
.
common
.
cache
;
import
com.google.common.cache.Cache
;
import
com.google.common.cache.CacheBuilder
;
import
org.springframework.data.redis.core.ValueOperations
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.TimeUnit
;
import
java.util.function.Supplier
;
/**
* 通用两级缓存模板:L1(Guava本地缓存)→ L2(Redis分布式缓存)→ L3(数据库回调查询)
* <p>
* 使用示例:
* <pre>{@code
* @Resource
* private CacheTemplate cacheTemplate;
*
* public Result getCmpt(@PathVariable Integer cmptId) {
* Cmpt cmpt = cacheTemplate.get(
* "cmpt:info", // 缓存命名空间
* String.valueOf(cmptId), // 缓存键
* Cmpt.class, // 返回值类型
* 2L, TimeUnit.MINUTES, // L1本地TTL
* 5L, TimeUnit.MINUTES, // L2 Redis TTL
* () -> cmptService.queryCmptBycmptId(cmptId) // L3 DB回调
* );
* return Result.success().setContent(cmpt);
* }
* }</pre>
*
* @author generated
*/
@Component
public
class
CacheTemplate
{
@Resource
private
ValueOperations
<
String
,
Object
>
valueOperations
;
/** 各命名空间对应的本地 Guava 缓存,按需创建 */
private
final
ConcurrentHashMap
<
String
,
Cache
<
String
,
Object
>>
localCaches
=
new
ConcurrentHashMap
<>();
/** 默认本地缓存最大容量 */
private
static
final
int
DEFAULT_LOCAL_MAX_SIZE
=
1000
;
/** Redis key 统一前缀 */
private
static
final
String
REDIS_KEY_PREFIX
=
"gk:"
;
/**
* 两级缓存查询(自动降级:L1 → L2 → L3)
*
* @param namespace 缓存命名空间,如 "cmpt:info",用于区分不同业务
* @param key 缓存键,同一命名空间下唯一
* @param type 返回值类型 Class 对象
* @param localTtl 本地缓存过期时间数值
* @param localTtlUnit 本地缓存过期时间单位
* @param redisTtl Redis 缓存过期时间数值
* @param redisTtlUnit Redis 缓存过期时间单位
* @param dbLoader 数据库加载回调,仅在两级缓存均未命中时调用
* @param <T> 返回值泛型
* @return 缓存命中返回缓存值,否则执行 dbLoader 并回填两级缓存后返回
*/
public
<
T
>
T
get
(
String
namespace
,
String
key
,
Class
<
T
>
type
,
long
localTtl
,
TimeUnit
localTtlUnit
,
long
redisTtl
,
TimeUnit
redisTtlUnit
,
Supplier
<
T
>
dbLoader
)
{
// L1: 查本地 Guava 缓存
Cache
<
String
,
Object
>
localCache
=
getOrCreateLocalCache
(
namespace
,
localTtl
,
localTtlUnit
);
Object
cached
=
localCache
.
getIfPresent
(
key
);
if
(
cached
!=
null
)
{
return
type
.
cast
(
cached
);
}
// L2: 查 Redis 分布式缓存
String
redisKey
=
REDIS_KEY_PREFIX
+
namespace
+
":"
+
key
;
Object
redisCached
=
valueOperations
.
get
(
redisKey
);
if
(
redisCached
!=
null
&&
type
.
isInstance
(
redisCached
))
{
T
result
=
type
.
cast
(
redisCached
);
localCache
.
put
(
key
,
result
);
// 回填 L1
return
result
;
}
// L3: 查数据库,同时回填两级缓存
T
result
=
dbLoader
.
get
();
if
(
result
!=
null
)
{
localCache
.
put
(
key
,
result
);
valueOperations
.
set
(
redisKey
,
result
,
redisTtl
,
redisTtlUnit
);
}
return
result
;
}
/**
* 清除指定命名空间下某个 key 的全部缓存(L1 + L2)
*
* @param namespace 缓存命名空间
* @param key 缓存键
*/
public
void
evict
(
String
namespace
,
String
key
)
{
Cache
<
String
,
Object
>
localCache
=
localCaches
.
get
(
namespace
);
if
(
localCache
!=
null
)
{
localCache
.
invalidate
(
key
);
}
valueOperations
.
getOperations
().
delete
(
REDIS_KEY_PREFIX
+
namespace
+
":"
+
key
);
}
/**
* 清除指定命名空间的全部本地缓存(L1 only)
*/
public
void
evictLocal
(
String
namespace
)
{
Cache
<
String
,
Object
>
localCache
=
localCaches
.
get
(
namespace
);
if
(
localCache
!=
null
)
{
localCache
.
invalidateAll
();
}
}
/**
* 按需创建本地缓存实例
*/
private
Cache
<
String
,
Object
>
getOrCreateLocalCache
(
String
namespace
,
long
ttl
,
TimeUnit
unit
)
{
return
localCaches
.
computeIfAbsent
(
namespace
,
name
->
CacheBuilder
.
newBuilder
()
.
maximumSize
(
DEFAULT_LOCAL_MAX_SIZE
)
.
expireAfterWrite
(
ttl
,
unit
)
.
recordStats
()
.
build
()
);
}
}
src/main/java/com/dlbridge/jadp/config/web/WebConfig.java
View file @
d37316ac
...
...
@@ -45,8 +45,7 @@ public class WebConfig implements WebMvcConfigurer {
FastJsonHttpMessageConverter
fastJsonConverter
=
new
FastJsonHttpMessageConverter
();
FastJsonConfig
config
=
new
FastJsonConfig
();
config
.
setWriterFeatures
(
JSONWriter
.
Feature
.
WriteMapNullValue
,
JSONWriter
.
Feature
.
WriteDateUseDateFormat
JSONWriter
.
Feature
.
WriteMapNullValue
);
config
.
setDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
fastJsonConverter
.
setFastJsonConfig
(
config
);
...
...
src/main/java/com/dlbridge/jadp/plugins/cmpt/web/MicroApiController.java
View file @
d37316ac
...
...
@@ -3,6 +3,7 @@ package com.dlbridge.jadp.plugins.cmpt.web;
import
com.alibaba.fastjson2.JSONObject
;
import
com.dlbridge.feign.NewsService
;
import
com.dlbridge.feign.bean.News
;
import
com.dlbridge.jadp.common.cache.CacheTemplate
;
import
com.dlbridge.jadp.common.service.JService
;
import
com.dlbridge.jadp.job.CountJob
;
import
com.dlbridge.jadp.plugins.cmpt.bean.Contact
;
...
...
@@ -48,7 +49,9 @@ import java.util.concurrent.TimeUnit;
@ApiSort
(
1
)
public
class
MicroApiController
{
private
static
final
String
SIGNING_CODE
=
"1"
;
private
static
final
long
CMPT_CACHE_EXPIRE_MINUTES
=
5L
;
@Resource
private
CacheTemplate
cacheTemplate
;
@Resource
private
RestTemplate
restTemplate
;
...
...
@@ -414,36 +417,14 @@ public class MicroApiController {
@ApiResponses
({
@ApiResponse
(
code
=
200
,
message
=
"成功"
),
@ApiResponse
(
code
=
-
1
,
message
=
"失败"
,
response
=
ObjectUtils
.
Null
.
class
),
@ApiResponse
(
code
=
200
,
message
=
"成功"
,
response
=
Result
.
class
,
responseContainer
=
"List"
)})
@ApiOperation
(
value
=
"赛事"
,
notes
=
"赛事"
,
tags
=
{
"首页接口"
})
public
Result
getCmpt
(
@PathVariable
(
"cmptId"
)
Integer
cmptId
)
{
long
startTime
=
System
.
currentTimeMillis
();
// 先从Redis缓存中获取
String
cacheKey
=
"gk:cmpt:info:"
+
cmptId
;
Object
cachedObj
=
valueOperations
.
get
(
cacheKey
);
if
(
cachedObj
!=
null
&&
cachedObj
instanceof
Cmpt
)
{
Cmpt
cachedCmpt
=
(
Cmpt
)
cachedObj
;
long
costTime
=
System
.
currentTimeMillis
()
-
startTime
;
log
.
info
(
"[缓存命中] 从缓存中获取赛事信息,cmptId: {}, 耗时: {}ms"
,
cmptId
,
costTime
);
return
Result
.
success
().
setContent
(
cachedCmpt
);
}
log
.
info
(
"[缓存未命中] 开始查询数据库,cmptId: {}"
,
cmptId
);
long
dbStartTime
=
System
.
currentTimeMillis
();
Cmpt
cmpt
=
cmptService
.
queryCmptBycmptId
(
cmptId
);
long
dbCostTime
=
System
.
currentTimeMillis
()
-
dbStartTime
;
log
.
info
(
"[数据库查询] 查询完成,cmptId: {}, 耗时: {}ms"
,
cmptId
,
dbCostTime
);
if
(
cmpt
!=
null
)
{
long
cacheStartTime
=
System
.
currentTimeMillis
();
valueOperations
.
set
(
cacheKey
,
cmpt
,
CMPT_CACHE_EXPIRE_MINUTES
,
TimeUnit
.
MINUTES
);
long
cacheCostTime
=
System
.
currentTimeMillis
()
-
cacheStartTime
;
log
.
info
(
"[缓存设置] 赛事信息已缓存,cmptId: {}, 耗时: {}ms"
,
cmptId
,
cacheCostTime
);
}
long
totalCostTime
=
System
.
currentTimeMillis
()
-
startTime
;
log
.
info
(
"[总耗时] cmptId: {}, 总耗时: {}ms"
,
cmptId
,
totalCostTime
);
Cmpt
cmpt
=
cacheTemplate
.
get
(
"cmpt:info"
,
// 缓存命名空间
String
.
valueOf
(
cmptId
),
// 缓存键
Cmpt
.
class
,
// 返回值类型
2L
,
TimeUnit
.
MINUTES
,
// L1 本地缓存 TTL
5L
,
TimeUnit
.
MINUTES
,
// L2 Redis 缓存 TTL
()
->
cmptService
.
queryCmptBycmptId
(
cmptId
)
// L3 数据库回调
);
return
Result
.
success
().
setContent
(
cmpt
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment