spring-boot整合redis作为缓存(3)——自定义key

        分几篇文章总结 spring-boot与 Redis的整合

        1、redis的安装

        2、redis的设置

        3、spring-boot的缓存

        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为乱码的问题,这个在后一篇文章中会说明


你可能感兴趣的:(redis,java,java,web)