3. Spring Cache + Redis cache data

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);
   }
}