Article directory
- 1. Spring Cache + Redis cache data
-
- 1. Project integration Spring Cache + Redis
-
- 1.1 service-util add dependencies
- 1.2 service-util add configuration class
- 1.3 service-cmn add redis configuration
- 2. Use Spring Cache
-
- 2.1 Common cache tags
-
- 2.1.2 Cache @Cacheable
- 2.1.2 Cache @CachePut
- 2.1.3 Cache @CacheEvict
- 2.2 Data dictionary application
1. Spring Cache + Redis cache data
Spring Cache is a very good caching component. Since Spring 3.1, it provides annotation Cache support similar to @Transactional annotation transactions, and provides Cache abstraction to facilitate switching of various underlying Cache (such as: redis)
Benefits of using Spring Cache:
?1. Provide basic Cache abstraction to facilitate switching of various underlying Cache;
?2. By annotating Cache, similar to transactions, cache logic can be transparently applied to our business code, and it can be completed with less code;
?3, automatically roll back the cache when providing transaction rollback;
?4, support more complex cache logic;
1. Project integration Spring Cache + Redis
Because the cache is also used publicly, all service modules may use the cache, so we add dependencies and some configurations to the service-util module, so that other service modules can use it
1.1 service-util add dependencies
Add dependencies to the pom.xml of the service-util module
<!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- common-pool2 required for spring2.X integrated redis --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.6.0</version> </dependency>
1.2 service-util add configuration class
Create com.atguigu.yygh.common.config.RedisConfig
package com.atguigu.yygh.common.config; @Configuration @EnableCaching public class RedisConfig {<!-- --> /** * Custom key rules * @return */ @Bean public KeyGenerator keyGenerator() {<!-- --> return new KeyGenerator() {<!-- --> @Override public Object generate(Object target, Method method, Object... params) {<!-- --> StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) {<!-- --> sb.append(obj.toString()); } return sb.toString(); } }; } /** * Set RedisTemplate rules * @param redisConnectionFactory * @return */ @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {<!-- --> RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); // Solve the problem of query cache conversion exception ObjectMapper om = new ObjectMapper(); // Specify the domain to be serialized, field, get and set, and the range of modifiers, ANY includes private and public om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // Specify the type of serialized input, the class must be non-final modified, final modified classes, such as String, Integer, etc. will run out of exception om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); //serial number key value redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } /** * Set CacheManager cache rules * @param factory * @return */ @Bean public CacheManager cacheManager(RedisConnectionFactory factory) {<!-- --> RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); // Solve the problem of query cache conversion exception ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // Configure serialization (to solve the problem of garbled characters), the expiration time is 600 seconds RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; } }
illustrate:
@EnableCaching: Mark annotation @EnableCaching, enable caching, and configure the Redis cache manager. The @EnableCaching annotation triggers a post-processor that checks each Spring bean’s public method for the presence of the caching annotation. If such an annotation is found, a proxy is automatically created to intercept the method call and handle the corresponding caching behavior.
1.3 service-cmn add redis configuration
spring.redis.host=192.168.44.165 spring.redis.port=6379 spring.redis.database = 0 spring.redis.timeout=1800000 spring.redis.lettuce.pool.max-active=20 spring.redis.lettuce.pool.max-wait=-1 #Maximum blocking waiting time (negative number means no limit) spring.redis.lettuce.pool.max-idle=5 spring.redis.lettuce.pool.min-idle=0
2. Use Spring Cache
2.1 Common cache tags
2.1.2 Cache @Cacheable
The returned result is cached according to the method. When the next request is made, if the cache exists, the cached data is directly read and returned; if the cache does not exist, the method is executed and the returned result is stored in the cache. Generally used in query methods.
View the source code, the property values are as follows:
Attribute/Method Name | Explanation |
---|---|
value | Cache name, required, it specifies which namespace your cache is stored in |
cacheNames | It is similar to value, just choose one of the two |
key | Optional attribute, you can use the SpEL tag to customize the cache key |
2.1.2 Cache @CachePut
The method marked with this annotation will be executed every time, and the result will be stored in the specified cache. Other methods can read cached data directly from the response cache without having to query the database. Generally used for adding methods.
View the source code, the property values are as follows:
Attribute/Method Name | Explanation |
---|---|
value | Cache name, required, it specifies which namespace your cache is stored in |
cacheNames | It is similar to value, just choose one of the two |
key | Optional attribute, you can use the SpEL tag to customize the cache key |
2.1.3 Cache @CacheEvict
The method using this annotation flag will clear the specified cache. Generally used in update or delete methods
View the source code, the property values are as follows:
Attribute/Method Name | Explanation |
---|---|
value | Cache name, required, it specifies which namespace your cache is stored in |
cacheNames | It is similar to value, just choose one of the two |
key | Optional attribute, you can use the SpEL tag to customize the cache key |
allEntries | Whether to clear all caches, the default is false. If specified as true, all caches will be cleared immediately after the method call |
beforeInvocation | Whether to clear before the method is executed, the default is false. If specified as true, the cache will be cleared before the method is executed |
2.2 Data dictionary application
Transform com.atguigu.yygh.cmn.service.impl.DictServiceImpl class method
/** * Get the child node data list according to the parent id * @param parentId */ @Cacheable(value = "dict",keyGenerator = "keyGenerator") @Override public List<Dict> findByParentId(Long parentId) {<!-- --> List<Dict> dictList = dictMapper.selectList(new QueryWrapper<Dict>().eq("parent_id", parentId)); dictList.stream().forEach(dict -> {<!-- --> boolean isHasChildren = this.isHasChildren(dict.getId()); dict.setHasChildren(isHasChildren); }); return dictList; } /** * import * allEntries = true: Clear all caches after the method call * @param file */ @CacheEvict(value = "dict", allEntries=true) @Override public void importData(MultipartFile file) {<!-- --> ExcelHelper fileHelper = new ExcelHelper(DictEeVo. class); List<DictEeVo> dictVoList = fileHelper. importExcel(file); if(!CollectionUtils.isEmpty(dictVoList)) {<!-- --> dictMapper.insertBatch(dictVoList); } }