1. Introduction
Last time we integrated Mybatis Plus, today we will integrate caching as well. Caching is an essential feature of a system application, in addition to relieving the pressure on the database. It also plays an important role in storing some short-lived data scenarios, such as storing user tokens and SMS verification codes, etc. At present, there are many types of cache, such as EHCACHE, HAZELCAST, CAFFEINE, COUCHBASE and REDIS to be integrated in this paper. Next we will integrate Spring Cache with Redis in the Kono scaffolding project.
Gitee: gitee.com/felord/kono day05 branch
Making: github.com/NotFound403… Day05 branch
2. Integrate goals
Make the project have cache function, change the default JDK serialization to Jackson serialization to store some objects, and realize some specific personalized cache space to meet different cache TTL requirements in different scenarios.
3. Dependency integration
Now you just need to introduce the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
Copy the code
By default, spring-data-redis uses a high-performance oracle client implementation, of course you can replace it with the old Jedis.
4. Cache and Redis configuration
Cache and Redis configuration items start with spring. Cache and spring. Redis respectively.
spring:
redis:
host: localhost
port: 6379
cache:
# type: REDIS
redis:
Global expiration time
time-to-live: 120
Copy the code
5. Personalize the RedisTemplate
By default, two template classes are injected into Spring IoC for our use, requiring personalized configuration for actual development.
The first is RedisTemplate
,>
/** * Some custom configurations of Redis. **@author felord.cn
* @since2020/8/17 men * /
@ConditionalOnClass(ObjectMapper.class)
@Configuration(proxyBeanMethods = false)
public class RedisConfiguration {
/**
* Redis template redis template.
*
* @param redisConnectionFactory the redis connection factory
* @return the redis template
*/
@Bean("redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
/ / use Jackson2JsonRedisSerialize replace the default serialization
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = initJacksonSerializer();
// Set the serialization rules for value and key
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
/** * Handle redis serialization@return Jackson2JsonRedisSerializer
*/
private Jackson2JsonRedisSerializer<Object> initJacksonSerializer(a) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
/ / the following om, replacing the old version. EnableDefaultTyping (ObjectMapper. DefaultTyping. NON_FINAL);
om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
//bugFix Jackson2 failed to deserialize data processing of type LocalDateTime
om.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);
Java8 time support
om.registerModule(new JavaTimeModule());
jackson2JsonRedisSerializer.setObjectMapper(om);
returnjackson2JsonRedisSerializer; }}Copy the code
The other one is StringRedisTemplate, which basically handles caching of strings with keys and values, which is fine by default.
6. Cache personalization
When using Spring Cache, there are scenarios where different expiration times are set for different keys. For example, I want to set Jwt Token to expire in a week, and CAPtchas to expire in five minutes. So how do we do that? We need to personalize RedisCacheManager. First I define these caches and their TTL times by enumeration. Such as:
/** * Cache definition enumeration **@author felord.cn
* @see cn.felord.kono.configuration.CacheConfiguration
* @since2020/8/17 so * /
public enum CacheEnum {
/** * User JWT token cache space TTL 7 days */
JWT_TOKEN_CACHE("usrTkn".7 * 24 * 60 * 60),
/** * Verification code cache for 5 minutes TTL */
SMS_CAPTCHA_CACHE("smsCode".5 * 60);
/** * Cache name */
private final String cacheName;
/** * Cache expiration seconds */
private final int ttlSecond;
CacheEnum(String cacheName, int ttlSecond) {
this.cacheName = cacheName;
this.ttlSecond = ttlSecond;
}
public String cacheName(a) {
return this.cacheName;
}
public int ttlSecond(a) {
return this.ttlSecond; }}Copy the code
This makes it very clear to describe the personalized cache.
Then we respectively by the Spring IoC injection RedisCacheConfiguration and RedisCacheManagerBuilderCustomizer to personalized configuration, you can keep an eye on how CacheEnum work. You can also customize these two configuration classes if you have other personalization needs.
import cn.felord.kono.enumeration.CacheEnum;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
import java.util.EnumSet;
import java.util.stream.Collectors;
/** * Redis cache configuration. **@author felord.cn
* @since17 then * / 2020/8 /
@EnableCaching
@Configuration
public class CacheConfiguration {
/**
* Redis cache configuration.
*
* @param redisTemplate the redis template
* @return the redis cache configuration
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(RedisTemplate<Object, Object> redisTemplate, CacheProperties cacheProperties) {
/ / see spring. Cache. Redis
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
// Cache serialization issues
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(redisTemplate.getValueSerializer()));
if(redisProperties.getTimeToLive() ! =null) {
// Global TTL time
redisCacheConfiguration = redisCacheConfiguration.entryTtl(redisProperties.getTimeToLive());
}
if(redisProperties.getKeyPrefix() ! =null) {
// Key prefix value
redisCacheConfiguration = redisCacheConfiguration.prefixCacheNameWith(redisProperties.getKeyPrefix());
}
if(! redisProperties.isCacheNullValues()) {// The default cache null value prevents cache penetration
redisCacheConfiguration = redisCacheConfiguration.disableCachingNullValues();
}
if(! redisProperties.isUseKeyPrefix()) {// Do not use the key prefix
redisCacheConfiguration = redisCacheConfiguration.disableKeyPrefix();
}
return redisCacheConfiguration;
}
/** * Redis Cache Manager personalizes the cache expiration time. *@see RedisCacheManager,CacheEnum
* @return the redis cache manager builder customizer
*/
@Bean
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer(RedisCacheConfiguration redisCacheConfiguration) {
return builder -> builder.cacheDefaults(redisCacheConfiguration)
// Some custom cache configuration initializations are mainly for the specific cache and its TTL time.withInitialCacheConfigurations(EnumSet.allOf(CacheEnum.class).stream() .collect(Collectors.toMap(CacheEnum::cacheName, cacheEnum -> redisCacheConfiguration.entryTtl(Duration.ofSeconds(cacheEnum.ttlSecond()))))); }}Copy the code
The Spring Cache support can also be enabled through the @enablecaching annotation. Details about Spring Cache can be found in the article Spring Cache.
Note that the effect above is achieved only through Spring Cache operations. Command line operations require explicit declarative instructions.
7. To summarize
Recently, I have a lot of things to do, so I seldom spare time to do something. If you encounter functions that need to be integrated in actual development, you can also tell me, and if you find some defects or bugs in the integration, please submit an ISSUE. More attention: code farmers xiao Pangge, with me to integrate the development of scaffolding.
Follow our public id: Felordcn for more information
Personal blog: https://felord.cn