Springboot 2.0.x Redis快取Key生成器,自定義生成器
阿新 • • 發佈:2018-11-27
文章目錄
Springboot 2.0.x Redis快取Key生成器,自定義生成器
1、預設的Key生成策略
首先看看生成器介面的原始碼
package org.springframework.cache.interceptor; import java.lang.reflect.Method; /** * Cache key generator. Used for creating a key based on the given method * (used as context) and its parameters. * * @author Costin Leau * @author Chris Beams * @author Phillip Webb * @since 3.1 */ @FunctionalInterface public interface KeyGenerator { /** * Generate a key for the given method and its parameters. * @param target the target instance * @param method the method being called * @param params the method parameters (with any var-args expanded) * @return a generated key */ // 介面提供三個引數,目標類,目標方法,目標引數列表 Object generate(Object target, Method method, Object... params); }
然後看預設的Key 生成策略
package org.springframework.cache.interceptor; import java.lang.reflect.Method; /** * Simple key generator. Returns the parameter itself if a single non-null * value is given, otherwise returns a {@link SimpleKey} of the parameters. * * <p>No collisions will occur with the keys generated by this class. * The returned {@link SimpleKey} object can be safely used with a * {@link org.springframework.cache.concurrent.ConcurrentMapCache}, however, * might not be suitable for all {@link org.springframework.cache.Cache} * implementations. * * @author Phillip Webb * @author Juergen Hoeller * @since 4.0 * @see SimpleKey * @see org.springframework.cache.annotation.CachingConfigurer */ public class SimpleKeyGenerator implements KeyGenerator { @Override public Object generate(Object target, Method method, Object... params) { return generateKey(params); } /** * Generate a key based on the specified parameters. * 預設的生成策略只是應用了引數列表 */ public static Object generateKey(Object... params) { if (params.length == 0) { // 如果沒有引數,就構建一個new Object[] 作為引數 return SimpleKey.EMPTY; } if (params.length == 1) { Object param = params[0]; if (param != null && !param.getClass().isArray()) { return param; } } return new SimpleKey(params); } }
然後是SimpleKey 的原始碼
/** * Create a new {@link SimpleKey} instance. * @param elements the elements of the key */ public SimpleKey(Object... elements) { // 首先斷言,引數列表不是null,否則丟擲 IllegalArgumentException Assert.notNull(elements, "Elements must not be null"); this.params = new Object[elements.length]; // 組裝引數作為Key System.arraycopy(elements, 0, this.params, 0, elements.length); this.hashCode = Arrays.deepHashCode(this.params); }
一般情況下,預設的Key生成策略,如果不同的包存在相同的引數列表和傳遞了相同的引數值,則在一定條件下,會導致訪問到錯誤的快取。所以我們重寫生成器,來避免這個問題
2、重寫生成器
import com.alibaba.fastjson.JSON;
import com.zyfycs.college.core.ModelContainer;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.cache.interceptor.KeyGenerator;
import java.lang.reflect.Method;
/**
* @author Created by 譚健 on 2018/11/21. 星期三. 14:53.
* © All Rights Reserved.
*/
public class RedisCacheKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object targetClass, Method method, Object... params) {
// 這裡可用HashMap
ModelContainer<String,Object> container = ModelContainer.newModelContainer();
Class<?> targetClassClass = targetClass.getClass();
// 類地址
container.put("class",targetClassClass.toGenericString());
// 方法名稱
container.put("methodName",method.getName());
// 包名稱
container.put("package",targetClassClass.getPackage());
// 引數列表
for (int i = 0; i < params.length; i++) {
container.put(String.valueOf(i),params[i]);
}
// 轉為JSON字串
String jsonString = JSON.toJSONString(container);
// 做SHA256 Hash計算,得到一個SHA256摘要作為Key
return DigestUtils.sha256Hex(jsonString);
}
}
DigestUtils 包
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
3、註冊自定義生成器
// 在 CacheConfig 中定義
@Bean
KeyGenerator keyGenerator(){
return new RedisCacheKeyGenerator();
}
// 該值是 keyGenerator 方法的方法名稱,如果Bean 指定了名稱,則使用指定的名稱
public static final String DEFAULT_KEY_GENERATOR = "keyGenerator";
// 定義快取區,快取區可以在配置時指定不同的過期時間,作為防止快取雪崩的一個保護措施
public static final String COMMON = "COMMON";
4、應用
@Cacheable(value = CacheConfig.COMMON,keyGenerator = CacheConfig.DEFAULT_KEY_GENERATOR)
5、在Redis 中Key的顯示
COMMON::b525f46bc5dac06113cb9a3a9c094231db3a20dcd89bf36edebfd14ae9ee1500