[Chapter 3] SpringBoot 2.x Integrated Redis-Cache

I mentioned earlier. [Chapter 2] SpringBoot 2.x Integrated Redis And the basic use of redis in SpringBoot.
This article mainly talks about the basic use of Redis database as Cache in SpringBoot.

Introducing dependencies

<!-- redis starter -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- lettuce pool Cache connection pool -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
</dependency>

When SpringBoot imports spring-boot-starter-data-redis, there is no need to introduce other dependencies.
Cache Manager defaults to RedisCache.

If the project is not cached with Redis, you need to introduce:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

application.yml configuration

spring:
  redis:
    # Redis database index (default 0)
    database: 0
    # Redis Server Connection Port
    port: 6379
    # Redis server address
    host: 127.0.0.1
    # Redis server connection password (default is empty)
    password: 123456
    # Connection timeout time (milliseconds)
    timeout: 5000
    lettuce:
      # Close timeout
      shutdown-timeout: 100
      pool:
        # Maximum number of connections in connection pool (no restrictions with negative values)
        max-active: 8
        # Maximum blocking waiting time for connection pools (using negative values to indicate no restrictions)
        max-wait: 10000
        # Maximum idle connection in connection pool
        max-idle: 8
        # Minimum idle connection in connection pool
        min-idle: 0

Open the cache @EnableCaching and configure Cache Manager, Key Generator

  • @ EnableCaching: Open Caching
  • Cache Manager: Spring Cache Manager
  • KeyGenerator: Redis cache Key generation strategy. Spring's default DefaultKeyGenerator generates keys based on parameter lists. When the values of parameter lists are the same, it will cause the wrong cache data to be retrieved.
import com.alibaba.fastjson.JSONObject;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.StringJoiner;

/**
 * @Title: RedisCacheConfig
 * @Description: TODO(reids Cache configuration)
 * @Author flyingkid
 * @Date 2019/6/5 11:36 p.m.
 */
@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {


    /**
     * @description TODO Cache key prefix
     */
    private static final String keyPrefix = "CACHE:";

    /**
     * The Strategy of Cache Generating key
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringJoiner joiner = new StringJoiner(":",keyPrefix,"");
            joiner.add(target.getClass().getSimpleName());
            joiner.add(method.getName());

            for (Object param : params) {
                joiner.add(JSONObject.toJSONString(param));
            }
            return joiner.toString();
        };
    }

    /**
     * RedisTemplate To configure
     */
    @Bean
    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(keySerializer());
        redisTemplate.setHashKeySerializer(keySerializer());
        redisTemplate.setValueSerializer(valueSerializer());
        redisTemplate.setHashValueSerializer(valueSerializer());
        return redisTemplate;
    }


    /**
     * Managing Cache
     */
    @Bean
    @Primary
    public CacheManager cacheManager(LettuceConnectionFactory factory){
        //Cache configuration object
        RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                //Setting the default timeout time for caching: 30 minutes
                .entryTtl(Duration.ofMinutes(30L))
                //If null, no caching
                .disableCachingNullValues()
                //Setting up key serializer
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                //Setting up value serializer
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer((valueSerializer())));

        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
                .cacheDefaults(cacheConfig).build();
    }
    /**
     * key serialize
     */
    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }
    /**
     * value serialize
     */
    private RedisSerializer<Object> valueSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }
}

Note: String Joiner is a tool class provided by Java 8 for String string splicing, new String Joiner (":", "keyPrefix");
The first parameter of the constructor represents splicing separated by colons. The second parameter is prefix and the third parameter is suffix. Interested partners can read the java.util.String Joiner source code.

Basic use of caching

import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * @ClassName: ExampleService
 * @Description: TODO redis cache
 * @Author: Gone with the Wind Boy
 */
@Slf4j
@Service
@CacheConfig(keyGenerator = "keyGenerator") //This is a unified key generation strategy for this class
public class ExampleService {

    /**
     * @description TODO  Add Cache
     * @param name
     */
    @Override
    @Cacheable(value = "addCache")
    public String addCache(String name) {
        return "Love float de Boy";
    }

    /**
     * @description TODO Delete Cache
     * @param name
     */
    @Override
    @CacheEvict(value = "addCache",allEntries=true)
    public void delCache(String name) {

    }
}


Cache annotations in detail

@Cacheable

Add in methods, add caches according to conditions

  • value: Cache name, not empty
  • cacheNames: Cache name, and value alternative
  • Key: The cached key, which defaults to null, represents the parameter type and value of the method used as key and supports SpEL
  • keyGenerator: Generation strategy for specifying key s
  • cacheManager: Specify the cache manager
  • cacheResolver: Specifies the fetch parser
  • condition: Cache if conditions are met
  • unless: Conditions are met without caching
  • sync: Default false using asynchronous mode

@CachePut

Add in methods, add caches according to conditions

@ CachePut acts like @Cacheable, except that @Cacheable executes methods without caching data, caches the results, and invokes methods for the second time without executing methods, retrieves data directly from the cache and returns it.
@ CachePut executes methods every time, regardless of whether there is data in the cache, it caches the results.

@CacheEvict

Add in the method, empty the cache according to the condition.

  • value: Cache name, not empty
  • cacheNames: The name of the cache, alternative to value
  • KeyGenerator: Generator of keys. key/keyGenerator Optional Use
  • Condition: Trigger condition, SpEL support
  • AllEntries: true denotes the removal of all caches in value by default to false
  • beforeInvocation: Whether to clear default false before method execution
  • cacheManager: Specify the cache manager
  • cacheResolver: Or specify a fetch parser

@CacheConfig

Acts on classes to configure global properties for caching annotations of this class

  • cacheNames: Cache Names
  • KeyGenerator: Generator of keys
  • Cache Manager: Cache Manager
  • cacheResolver: Get the parser

@Caching

Combining multiple cache annotations

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {
    Cacheable[] cacheable() default {};

    CachePut[] put() default {};

    CacheEvict[] evict() default {};
}

Cacheable,CachePut,CacheEvict in Caching annotations are all array types. They can satisfy the method of adding or deleting multiple caches.

Tags: Redis Spring SpringBoot Java

Posted on Fri, 06 Sep 2019 06:37:42 -0700 by Pryach