Springboot 2.0.x Redis缓存Key生成器,自定义生成器

文章目录

  • Springboot 2.0.x Redis缓存Key生成器,自定义生成器
          • 1、默认的Key生成策略
          • 2、重写生成器
          • 3、注册自定义生成器
          • 4、应用
          • 5、在Redis 中Key的显示

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.
 *
 * 

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 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 包


			commons-codec
			commons-codec

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

你可能感兴趣的:(#,底层实现,/,性能优化,/,安全,#,Springboot源码,框架相关,-,SpringBoot体系,#,Redis)