refactor(cache): 纵深防御与风格清理(autoType/锁key/抖动上界/key校验/proxyBeanMethods)
- CacheValueCodec.decode 关闭 fastjson @type 自动类型(Feature.IgnoreAutoType): 纵深防御;经验证常规链路本已安全(指定目标类型时 @type 被忽略),此为显式锁定契约。 - 模板锁 key 改用 keyBuilder.buildLock(key),与 CacheKeyBuilder 单一来源,消除重复派生。 - applyJitter 上界改 nextLong(bound) 对齐 spec 半开区间 [ttl, ttl*(1+ratio));测试收紧为严格 <。 - CacheKeyBuilder.build 对空白 bizKey fail-fast,避免 "cache:null" 静默键碰撞。 - RedisCacheAutoConfiguration 用 @Configuration(proxyBeanMethods=false),省 CGLIB 代理开销。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package com.njcn.middle.cache.support;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class CacheKeyBuilderTest {
|
||||
|
||||
@@ -31,4 +32,12 @@ class CacheKeyBuilderTest {
|
||||
assertEquals("cache:prod:user:1:__lock__",
|
||||
new CacheKeyBuilder("cache:", true, "prod").buildLock("user:1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void buildRejectsBlankBizKey() {
|
||||
CacheKeyBuilder kb = new CacheKeyBuilder("cache:", false, "");
|
||||
assertThrows(IllegalArgumentException.class, () -> kb.build(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> kb.build(""));
|
||||
assertThrows(IllegalArgumentException.class, () -> kb.build(" "));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,4 +61,13 @@ class CacheValueCodecTest {
|
||||
void decodeDirtyStringThrows() {
|
||||
assertThrows(RuntimeException.class, () -> codec.decode("{not-json", Foo.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeIgnoresAtTypeHint() {
|
||||
// 含 @type 的脏值(如 Redis 值被外部篡改注入)应被忽略,安全解析为目标类型
|
||||
String raw = "{\"@type\":\"java.util.HashMap\",\"id\":1,\"name\":\"a\"}";
|
||||
Foo foo = codec.decode(raw, Foo.class);
|
||||
assertEquals(1L, foo.getId());
|
||||
assertEquals("a", foo.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,9 +111,9 @@ class RedisCacheEnhanceTemplateTest {
|
||||
void applyJitterWithinBounds() {
|
||||
props.setJitterRatio(0.1);
|
||||
long bound = (long) (100 * 0.1);
|
||||
for (int i = 0; i < 50; i++) {
|
||||
for (int i = 0; i < 500; i++) {
|
||||
long ttl = template.applyJitter(100);
|
||||
assertTrue(ttl >= 100 && ttl <= 100 + bound, "ttl=" + ttl);
|
||||
assertTrue(ttl >= 100 && ttl < 100 + bound, "ttl=" + ttl); // 半开区间 [100,110)
|
||||
}
|
||||
props.setJitterRatio(0);
|
||||
assertEquals(100, template.applyJitter(100));
|
||||
|
||||
Reference in New Issue
Block a user