Implementation and application of SpringBoot redis cache

Implementation and application of SpringBoot redis cache

Foreword: before browsing this article, it is recommended to browse SpringBoot integration redis: https://blog.csdn.net/qq_27242695/article/details/112618063

1 add @EnableCaching to startup class

1.1 built in tomcat

@SpringBootApplication
@EnableCaching// Start cache
public class Application {

    /**
     * Internal tomcat startup entry
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

1.2 external tomcat

/**
 * Configure this class and start the external tomcat entry
 */
@SpringBootApplication
@EnableCaching// Start cache
public class TomcatServletInitializer extends SpringBootServletInitializer {


    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(TomcatServletInitializer.class);
    }
}

2 CacheManager cache manager

2.1 using the default cache manager

2.1.1 default cache manager initialization configuration

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        //1. sequence session (generally used for key value)
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        //2. introduce the conversion class of json string (generally used for value processing)
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        //2.1 setting the access permission of objectMapper
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //2.2 specifying the serialization input type is to store the data in the database into the redis cache according to a certain type.
        // objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);// During the recent upgrade of SpringBoot, it was found that the enabledefaulttyping method has expired. The following method can be used instead
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        //3. serial session configuration, garbled code problem resolution and timeliness of our cache. The cache expiration time is 30s
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().
                entryTtl(Duration.ofSeconds(30)).//Cache timeliness setting 30s
                serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).//key serialization
                serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).//value serialization
                disableCachingNullValues();//Null values are not stored in the cache
        //4. create a cacheManager link and set properties
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();
        return cacheManager;
    }

2.1.2 application.properties configuration

# Indicates that the current framework uses redis caching
spring.cache.type=redis
# Configure the redis cache space name. You may not configure it
spring.cache.cache-names=redis_cache

2.1.3 verification

  1. Pseudocode
    // Value: Specifies the redis cache storage space, which cannot be empty key: the key value suffix, which cannot be empty
    // In the default cache manager, all cache storage cycles are consistent, independent of the value cache space
    // Finally, it is stored in the key:student:: student of redis_# id
    @Cacheable(value = "student", key = "'student_'+#id")
    @RequestMapping("/cash/student")
    public Student saveStudent(String id) {
        System.out.println("student_id:" + id);
        return studentService.save();
    }
  1. redis key storage form
# key
student::student_#id
# value type
String

2.2 customize cache manager initialization configuration

2.2.1 default cache manager initialization configuration

/**
     * Custom cache manager
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        //1. sequence session (generally used for key value)
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        //2. introduce the conversion class of json string (generally used for value processing)
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        //2.1 setting the access permission of objectMapper
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //2.2 specifying the serialization input type is to store the data in the database into the redis cache according to a certain type.
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        // 3. set cache
        Set<String> cacheNames = new HashSet<>();
        cacheNames.add("student");
        cacheNames.add("order");
        cacheNames.add("permanent");

        // 4. set the cache for the cache and configure RedisCacheConfiguration
        ConcurrentHashMap<String, RedisCacheConfiguration> configMap = new ConcurrentHashMap<>();
        RedisCacheConfiguration studentCacheConfig = RedisCacheConfiguration.defaultCacheConfig().
                entryTtl(Duration.ofSeconds(30)).//Cache timeliness setting 30s
                serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).//key serialization
                serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).//value serialization
                disableCachingNullValues();//Null values are not stored in the cache
        configMap.put("student", studentCacheConfig);//Valid for 30s

        RedisCacheConfiguration orderCacheConfig = RedisCacheConfiguration.defaultCacheConfig().
                entryTtl(Duration.ofMinutes(1L)).//Cache timeliness setting 1min
                serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).//key serialization
                serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).//value serialization
                disableCachingNullValues();//Null values are not stored in the cache
        configMap.put("order", orderCacheConfig);//Valid for 1min

        RedisCacheConfiguration permanentConfig = RedisCacheConfiguration.defaultCacheConfig().
                serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).//key serialization
                serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).//value serialization
                disableCachingNullValues();//Null values are not stored in the cache
        configMap.put("permanent", permanentConfig);//Term of validity permanent

        //You need to initialize the cache name before initializing other configurations.
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory).initialCacheNames(cacheNames).withInitialCacheConfigurations(configMap).build();

        return cacheManager;
    }

2.2.2 application.properties configuration

# Indicates that the current framework uses redis caching
spring.cache.type=redis

2.2.3 verification

  1. Pseudocode
	// value specifies the redis cache of the student
	// Storage cycle: 30s
	@Cacheable(value = "student", key = "'student_'+#id")
    @RequestMapping("/cash/student")
    public Student saveStudent(String id) {
        System.out.println("student_id:" + id);
        return studentService.save();
    }

	// value specifies the redis cache of the order
	// Storage cycle: 1min
    @Cacheable(value = "order", key = "'order_'+#id")
    @RequestMapping("/cash/order")
    public Order saveOrder(String id) {
        System.out.println("order_id:" + id);
        return orderService.save();
    }


	// value specify the redis cache of permanent]
	// Storage cycle: permanent
    @Cacheable(value = "permanent", key = "'permanent'+#id")
    @RequestMapping("/cash/permanent")
    public Order save(String id) {
        System.out.println("permanent:" + id);
        return orderService.save();
    }

	// value=none, there is no none cache in the current configuration, and the default storage cycle is permanent
	// key generation rule: none::student_#id
    @Cacheable(value = "none", key = "'student_'+#id")
    @RequestMapping("/cash/student1")
    public Student saveNone(String id) {
        System.out.println("none_id:" + id);
        return studentService.save();
    }

3 Introduction to spring related cache annotations

3.1 @Cacheable annotation

@The Cacheable annotation is used by Spring to find the return value of the method in the cache before calling the method (Note: before calling the method). The default key is generated according to the parameter value. If it exists, it directly returns the value in the cache. Otherwise, the method is executed and the return value is saved in the cache

3.1.1 @Cacheable execution process

  1. Before the method runs, first query the cache (cache component) and obtain it according to the name specified by cacheNames; If it is not found, create a cache component, and the retrieval here is completed by the CacheManager.
  2. In the found cache component, a parameter key is used to obtain the contents of the cache. By default, it is the parameter of the method where the @Cacheable annotation is located.
  3. If no cached data is found, the target method is called to get it.
  4. After the method executes a return, the returned data is stored in the cache through the AOP facet technology.

3.1.2 @Cacheable other attributes

  1. cacheNames/value: Specifies the name of the cache component and the cache in which the return value of the method is stored. It is an array method. Multiple caches can be specified.
  2. Key: the key used when caching data. This attribute can be used to specify. By default, the value of the method parameter is used You can use the SqEL expression to specify, for example, the value of the \id method parameter ID, \a0 \p0 \root Args[0] represents the first parameter. Refer to the following figure for more values:
  3. keyGenerator: the generator of the key. You can specify the id of the generation component of the key. That is, if the key does not want to be specified by using the key attribute, you can use this parameter to customize the generation rules. You can choose between key and keyGenerator Examples are as follows:
    Here, we create a new configuration class as follows:
@Configuration
public class MyCacheConfig {

    @Bean("myKeyGenerator")
    public KeyGenerator keyGenerator(){
        return new KeyGenerator(){

            @Override
            public Object generate(Object target, Method method, Object... params) {
                //Get the method name where the @Cacheable annotation is located and add [and the value of the parameter, plus], and use this as the key for caching
                return method.getName()+"["+ Arrays.asList(params).toString()+"]";
            }
        };
    }
}
  1. CacheManager: specify a cache manager, or use CacheResolver to specify a fetch parser.
  2. Condition: cache data only when this condition is met For example, condition = "\id>1" means that the parameter ID must be greater than 1 before caching
  3. Unless: negative caching. When the condition specified by unless is true, the return value of the method will not be cached; The results can be obtained for judgment, such as
    Unless = "\result = = null" or unless = "\a0==2": if the value of the first parameter is 2, the result is not cached.
  4. sync: whether to use asynchronous mode. The default value is false. Note that if asynchronous is enabled, the unless attribute is not supported.

3.2 @CachePut: call method and update cache

3.2.1 @CachePut execution process

  1. Call the target method first.
  2. Add the method result to the cache and update it if it already exists.

Note: when using this annotation to update the cache, the cached key must be consistent with the key specified in the @Cacheable annotation, otherwise it cannot be updated normally

3.2.2 @CachePut other attributes

Completely consistent with other properties of @Cacheable

3.3 @CacheEvict: clear cache

3.3.1 @CacheEvict attribute

  1. Key: Specifies the key of the cache to delete
  2. allEntries: specifies to clear all data of the key in the cache. The default value is false
  3. beforeInvocation: whether to clear the cache before or after method execution The default value is false, which means that the method is cleared after execution (if an exception occurs during the method execution, the cached data will not be deleted)

3.4 @@CacheConfig: extract public configuration

We can use the @CacheConfig annotation on the class to extract common parts:

@CacheConfig(cacheNames="student" ,cacheManager = "cacheManager")

Tags: Redis Spring Boot

Posted by billy2shoe on Fri, 03 Jun 2022 12:14:15 +0530