1. 程式人生 > >spring-boot整合redis作為快取(3)——自定義key

spring-boot整合redis作為快取(3)——自定義key

        分幾篇文章總結spring-boot與Redis的整合

        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為亂碼的問題,這個在後一篇文章中會說明