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
- 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(); }
- 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
- 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
- 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.
- 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.
- If no cached data is found, the target method is called to get it.
- 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
- 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.
- 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:
- 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()+"]"; } }; } }
- CacheManager: specify a cache manager, or use CacheResolver to specify a fetch parser.
- 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
- 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. - 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
- Call the target method first.
- 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
- Key: Specifies the key of the cache to delete
- allEntries: specifies to clear all data of the key in the cache. The default value is false
- 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")