Использование Redis для реализации кэширования в SpringBoot

Redis задняя часть база данных Spring

Spring Data Redis инкапсулирует различные операции клиента Redis для упрощения использования.

  • Когда Redis работает как база данных или очередь сообщений, мы обычно используем RedisTemplate для работы
  • Когда Redis используется в качестве кеша, мы можем использовать его как реализацию Spring Cache и использовать его напрямую через аннотации.

Для использования RedisTemplate см.:блог Brother space.com/spring boot R…

Ниже приводится краткое описание использования Redis в качестве кэша.

импортировать зависимости

SpringBoot начинается с версии 1.4,spring-boot-starter-redisЗависимость переименована.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>1.5.2.RELEASE</version>
</dependency>

конфигурационный файл

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 0
    database: 0
    pool:
      max-active: 8
      max-wait: -1
      max-idle: 8
      min-idle: 0

Таким образом, SpringBoot автоматически настроит Redis, внедрит связанные bean-компоненты, и мы сможем использовать@CacheConfig,@Cacheable,@CachePut,@CacheEvict.

Проблемы при использовании аннотаций Cache

В коллекции объектов кеша кеш хранится в виде ключ-значение. Если кэшированный ключ не указан, SpringBoot будет использоватьSimpleKeyGeneratorСгенерировать ключ.

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) {
			return SimpleKey.EMPTY;
		}
		if (params.length == 1) {
			Object param = params[0];
			if (param != null && !param.getClass().isArray()) {
				return param;
			}
		}
		return new SimpleKey(params);
	}
}
	public SimpleKey(Object... elements) {
		Assert.notNull(elements, "Elements must not be null");
		this.params = new Object[elements.length];
		System.arraycopy(elements, 0, this.params, 0, elements.length);
		this.hashCode = Arrays.deepHashCode(this.params);
	}

Глядя на исходный код, можно обнаружить, что это ключ, сгенерированный с использованием комбинации параметров метода.На данный момент есть проблема:Если параметры двух методов одинаковы, но логика выполнения различна, кэш первого метода будет поражен при выполнении второго метода. Решение находится в@CacheableПараметр Notes Указывает ключ или владеть реализациейKeyGenerator, укажите KeyGenerator в аннотации. Но если таких случаев много, очень хлопотно указывать ключ и KeyGenerator для каждого из них.

Spring также предлагает решение: наследованиеCachingConfigurerSupportи переписатьkeyGenerator()

Вставьте код ниже:

@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Autowired
    private JedisConnectionFactory jedisConnectionFactory;

    @Bean
    public RedisTemplate redisTemplate() {
        StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public CacheManager cacheManager() {
        String[] cacheNames = {"app_default", "users", "blogs", "goods", "configs", "info"};
        RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate(), Arrays.asList(cacheNames));
        redisCacheManager.setDefaultExpiration(86400);
        return redisCacheManager;
    }

    @Bean
    public Cache cache() {
        return cacheManager().getCache("app_default");
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, objects) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append("::" + method.getName() + ":");
            for (Object obj : objects) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };
    }
}

В настоящее время кэшированный ключ представляет собой имя пакета + имя метода + список параметров, поэтому конфликтовать сложно.