一、介绍
Spring框架支持透明地向应用程序添加缓存对缓存进行管理,其管理缓存的核心是将缓存应用于操作数据的方法,从而减少操作数据的执行次数,同时不会对程序本身造成任何干扰。
Spring Boot继承了Spring框架的缓存管理功能,通过使用@EnableCaching注解开启基于注解的缓存支持,Spring Boot就可以启动缓存管理的自动化配置。
随着系统的访问量和复杂度的提高,我们可能需要进行分布式部署,分布式部署中需要解决的第一个问题就是session一致性问题,redis集中式存储session是解决session一致性的最优解决方案之一。
二、环境搭建
2.1、引入相关依赖坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
2.2、编写配置文件
spring:
redis:
host: #你的Redis服务器ip地址
port: 6379
password: #连接密码,Redis默认没有密码,如果设置了密码需要在这里填写上密码
pool:
max-idle: 8
min-idle: 0
max-active: 8
max-wait: 1
timeout: 3000 #连接超时时间,单位是ms,3000表示3s,如果连接的是远程Redis服务器,可以适当调大该值
session:
store-type: redis #设置采用redis作为session的实现
cache:
type: redis #设置采用redis作为cache实现
cache-names: default-cache-name #设置默认的cacheName的值
2.3、启动类设置
package com.zs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@SpringBootApplication
// 启用缓存
@EnableCaching
// 启用RedisHttpSession
@EnableRedisHttpSession
public class Application extends SpringBootServletInitializer {
// 使用外置 Tomcat 启动时,SpringBootServletInitializer,并覆盖configure()方法
// 若使用的是SpringBoot内置的Tomcat启动的,则不需要对此进行处理
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2.4、Redis配置类设置
package com.zs.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {
// 自定义缓存key生成策略
// 缓存对象集合中,缓存是以 key-value 形式保存的。当不指定缓存的 key 时,SpringBoot 会使用 SimpleKeyGenerator 生成 key
// 此处具体实现规则可以按照自己的需求进行自定义实现,这里采用 **类名称_方法名_参数列表** 的拼接
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, java.lang.reflect.Method method, Object... params) {
StringBuffer sb = new StringBuffer();
sb.append(target.getClass().getSimpleName());
sb.append("_");
sb.append(method.getName());
sb.append("_");
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@Bean
public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 使用JSON格式序列化对象,对缓存数据key和value进行转换
Jackson2JsonRedisSerializer<Object> jacksonSerial = new Jackson2JsonRedisSerializer<>(Object.class);
// 解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSerial.setObjectMapper(om);
// 设置RedisTemplate模板API的序列化方式为JSON
// 此处主要用于处理中文乱码的情况
template.setDefaultSerializer(jacksonSerial);
template.setValueSerializer(jacksonSerial);
template.setHashKeySerializer(jacksonSerial);
template.setHashValueSerializer(jacksonSerial);
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
三、注意事项
3.1、配置类不生效问题
原有系统可能之前设置过相关的cache配置,此时需要将原有的cache设置注释掉,才能使新的cache配置生效,例如我的项目原来有如下相关的配置,注释掉即可
package com.zs.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.*;
import javax.cache.CacheManager;
@Configuration
@EnableCaching
@AutoConfigureAfter(value = { MetricsConfiguration.class })
@AutoConfigureBefore(value = { WebConfigurer.class, DatabaseConfiguration.class })
public class CacheConfiguration {
private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
private CacheManager cacheManager;
public CacheConfiguration(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
}
3.2、序列化失败或者日期时间类型无法序列化
Jackson2JsonRedisSerializer 对ZonedDateTime序列化和反序列化时会出现问题,可以采取如下方式解决
@Column(name = "created_time")
@ApiModelProperty("创建时间")
@JsonSerialize(using = ZonedDateTimeSerializer.class)
private ZonedDateTime createdTime;
四、数据缓存使用
数据缓存的使用比较简单,基于注解的方式使得使用Redis进行数据缓存非常简单。
@Cacheable(value = "zs_dev",keyGenerator = "keyGenerator")
public List<TYField> getAllTYFields() {
log.debug("REST request to get all TYFields");
return tYFieldRepository.findAll();
}