spring-boot整合redis作為快取(3)——自定義key
阿新 • • 發佈:2019-01-03
分幾篇文章總結spring-boot與Redis的整合
注意:我為什麼要返回一個字串key.toString(),完全可以返回key。其實這裡是為了解決redis中key為亂碼的問題,這個在後一篇文章中會說明
4、自定義key
5、spring-boot引入Redis
在上一篇文章中說道key是用來分辨同一個快取中的快取資料的。key是可以自己制定的,也可以通過自定義一個KeyGenerator來進行生成。
所以我們自定義key的思路為:通過自定義一個KeyGenerator來生成自定義的key
自定義key
key可以為任何物件,我們要考慮的只有一件事,兩個key物件,如何判斷他們是否相等。所以很自然的我們想到重新實現它的hashCode和equals方法即可
自定義keyGenerator
自定義keyGenerator必須實現org.springframework.cache.interceptor.KeyGenerator介面,他有如下待實現方法
Object generate(Object target, Method method, Object... params)
引數:target為呼叫方法類的例項,method為呼叫的方法,params為呼叫方法傳入的引數
返回值:key物件
例項
這裡舉一個例子,也是很實用的例子,自定義一個key。key的相等邏輯為同一個類名,同一個方法名,同樣的傳參。
@Component("baseCacheKeyGenerator")
public class BaseCacheKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
Object key=new BaseCacheKey(target,method,params);
return key.toString();
}
}
public class BaseCacheKey implements Serializable{ private static final long serialVersionUID = -1651889717223143579L; private static final Logger logger = LoggerFactory.getLogger(BaseCacheKey.class); private final Object[] params; private final int hashCode; private final String className; private final String methodName; public BaseCacheKey(Object target, Method method, Object[] elements){ this.className=target.getClass().getName(); this.methodName=getMethodName(method); this.params = new Object[elements.length]; System.arraycopy(elements, 0, this.params, 0, elements.length); this.hashCode=generatorHashCode(); } private String getMethodName(Method method){ StringBuilder builder = new StringBuilder(method.getName()); Class<?>[] types = method.getParameterTypes(); if(types.length!=0){ builder.append("("); for(Class<?> type:types){ String name = type.getName(); builder.append(name+","); } builder.append(")"); } return builder.toString(); } @Override public boolean equals(Object obj){ if(this==obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; BaseCacheKey o=(BaseCacheKey) obj; if(this.hashCode!=o.hashCode()) return false; if(!Optional.ofNullable(o.className).orElse("").equals(this.className)) return false; if(!Optional.ofNullable(o.methodName).orElse("").equals(this.methodName)) return false; if (!Arrays.equals(params, o.params)) return false; return true; } @Override public final int hashCode() { return hashCode; } private int generatorHashCode() { final int prime = 31; int result = 1; result = prime * result + hashCode; result = prime * result + ((methodName == null) ? 0 : methodName.hashCode()); result = prime * result + Arrays.deepHashCode(params); result = prime * result + ((className == null) ? 0 : className.hashCode()); return result; } @Override public String toString() { logger.debug(Arrays.toString(params)); logger.debug(Arrays.deepToString(params)); return "BaseCacheKey [params=" + Arrays.deepToString(params) + ", className=" + className + ", methodName=" + methodName + "]"; } }
注意:我為什麼要返回一個字串key.toString(),完全可以返回key。其實這裡是為了解決redis中key為亂碼的問題,這個在後一篇文章中會說明