一、导入依赖
<!--spring-cache Redis start --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
考虑到需要连接数据库,还需要有以下依赖
<!-- springboot mybatis 整合包 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <!--MySQL依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
二、Redis的配置类
1、申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值,
2、创建模板类,做序列化处理
方式一:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.EnableCaching;
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;
@EnableCaching
@Configuration
public class RedisConfig {
/**
* 申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)
* 根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值
* @return
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return RedisCacheManager.create(redisConnectionFactory);
}
/**
* 创建数据存储模板类,做数据序列化处理
* @param factory
* @return
*/
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
// 创建一个模板类
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
// 将刚才的redis连接工厂设置到模板类中
template.setConnectionFactory(factory);
// 设置key的序列化器
template.setKeySerializer(new StringRedisSerializer());
// 设置value的序列化器
//使用Jackson 2,将对象序列化为JSON
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//json转对象类,不设置默认的会将json转成hashmap
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
return template;
}
}
方式二:
import org.springframework.cache.CacheManager;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@EnableCaching
@Configuration
public class RedisConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheManager redisCacheManager = new RedisCacheManager(
RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
// 设置缓存的有效时间,单位秒
this.getRedisCacheConfigurationWithTtl(600),
// 指定 key 策略
this.getRedisCacheConfigurationMap()
);
redisCacheManager.setTransactionAware(true);
return redisCacheManager;
}
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(16);
return redisCacheConfigurationMap;
}
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
// 指定使用GenericJackson2JsonRedisSerializer序列化方式
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(genericJackson2JsonRedisSerializer)
).entryTtl(Duration.ofSeconds(seconds));
return redisCacheConfiguration;
}
}
三、application.properties配置文件内容
server.port=8082 # redis相关配置 spring.redis.database=0 spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password=123456 # 连接池最大连接数(使用负值表示没有限制) srping.redis.jedis.pool.max-active =8 # 连接池最大阻塞等待时间(使用负值表示没有限制) srping.redis.jedis.pool.max-wait=-1ms # 连接池中的最大空闲连接 srping.redis.jedis.pool.max-idle=8 # 连接池中的最小空闲连接 srping.redis.jedis.pool.min-idle=0 # 连接超时时间(毫秒)默认是2000ms srping.redis.jedis.pool.timeout=2000ms ## Entry expiration in milliseconds. By default the entries never expire. spring.cache.type=redis spring.cache.cache-names=user spring.cache.redis.time-to-live= 1d #写入redis时是否使用键前缀。 spring.cache.redis.use-key-prefix= true #数据库 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/cache?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=123456
四、业务逻辑增加注解
@CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置
@Cacheable:主要方法返回值加入缓存。同时在查间时,会先从缓存中取,若不存在再次发起对数据库的访问。
@CachePut:配置于函数上,能够根据参数定义条件进行缓存,与@Cacheable不同的是,每次会真实的调用函数,所以主要用于数据新增和修改操作上。
@CacheEvict:配置于函数上,通常用在删除方法上,用来从缓存中移除对应的数据
@Cachina:置于函数上,组合多个Cache注解使用
特殊说明:以下这两种配置等价
@Cacheable(value = "user")
//@Cacheable(cacheNames = "user")
Person getUserName(Integer id);
五:例子
//实体类需要进行序列化 @ApiModel("用户实体类") @Data @AllArgsConstructor @NoArgsConstructor public class User implements Serializable { @ApiModelProperty("ID") @Min(value = 1,message = "id应该在1-100之间") @Max(value = 100000,message = "id应该在1-100之间") private Integer id; @ApiModelProperty("用户名") @Size(min = 1,max = 5,message = "姓名长度应该在1-5之间") public String username; @ApiModelProperty("密码") @Size(min = 1,max = 5,message = "密码长度应该在1-5之间") public String password;}
//业务实现类进行缓存处理
@Service @CacheConfig(cacheNames = "user") public class UserRedisServiceImpl implements UserRedisService { @Cacheable(value = "user", key = "'user_list_202205091505'") @Override public List<User> list() { System.out.println("=========list"); User user1 = new User(); user1.setId(1); user1.setName("老大"); User user2 = new User(); user2.setId(2); user2.setName("老二"); List<User> users = new ArrayList<>(); users.add(user1); users.add(user2); return users; } }//controller中通过swagger可以进行测试
@ApiOperation("写在controller的方法上的,测试swagger,同时也测试java bean validation,也测试Redis与springcache结合") @RestController public class UserController { @Autowired private UserRedisServiceImpl redisServiceImpl; @RequestMapping(value = "/getlist", method = RequestMethod.POST) public void getlist() { List<User> list = redisServiceImpl.list(); System.out.println(list); } @RequestMapping(value = "/getlist1", method = RequestMethod.POST) public List<User> getlist1() { List<User> list1 = redisServiceImpl.list1(); System.out.println("<===list1===>" + list1); return list1; } }
查看缓存效果
补充知识点:
RedisTemplate和StringRedisTemplate的区别
- StringRedisTemplate继承了RedisTemplate。
- 两者的数据是不共通的;即:StringRedisTemplate只可以管理StringRedisTemplate里面的数据,RedisTemplate只可以管理RedisTemplate中的数据。
- SDR默认采用的序列化策略有两种:String的序列化策略、JDK的序列化策略
【StringRedisTemplate】默认采用String的序列化策略,保存的key和value都是采用此策略序列化进行保存。
【RedisTemplate】默认采用JDK的序列化策略,保存的key和value都是采用此策略序列化进行保存。
RedisTemplate使用的序列类在操作数据的时候,比如说存入数据会将数据先序列化成字节数组然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式展现的,而是以字节数组显示。当然从Redis获取数据的时候也会默认将数据当做字节数组转化。