目录
3.1 springboot 1.x自定义CacheManger
3.2 springboot 2.x自定义CacheManger
1. 缓存RedisTemplate
在我们没有配置其他缓存中间件的时候,默认使用的是ConcurrentMapCacheManager,ConcurrentMapCacheManager可以获取和创建ConcurrentMapCache类型的缓存组件,将数据保存在ConcurrentMap中。
而在开发的时候,大多数时候都要使用到缓存中间件,比如redis、ehcache等。本节就整合了redis,来实现缓存功能。
对于redis的基本操作,我前面已经做了一些基础介绍和使用方法的介绍:
参考链接:https://blog.csdn.net/chen_hao_181/article/category/9452823
本节还是采用以前的项目。
1.1 引入redis相关依赖
在pom文件中添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
然后再配置文件中(我使用的是yml文件)添加一个redis的主机ip,我使用的docker安装redis,你如果是本机安装就写localhost。
这样就成功引入了redis,接下来就可以使用redis了,redis和jdbc相似,可以使用RedisTemplate和StringRedisTemplate来操作redis,RedisTemplate用于key和value都是对象的时候,StringRedisTemplate用于操作String类型的数据。
1.2 RedisTemplate操作Reids
RedisTemplate和StringRedisTemplate都有一些相似的常用方法(StringRedisTemplate继承了RedisTemplate),如下所示:
public ListOperations<K, V> opsForList() {
if (listOps == null) {
listOps = new DefaultListOperations<>(this);
}
return listOps;
}
public SetOperations<K, V> opsForSet() {
if (setOps == null) {
setOps = new DefaultSetOperations<>(this);
}
return setOps;
}
public ValueOperations<K, V> opsForValue() {
if (valueOps == null) {
valueOps = new DefaultValueOperations<>(this);
}
return valueOps;
}
public ZSetOperations<K, V> opsForZSet() {
if (zSetOps == null) {
zSetOps = new DefaultZSetOperations<>(this);
}
return zSetOps;
}
public <HK, HV> HashOperations<K, HK, HV> opsForHash() {
return new DefaultHashOperations<>(this);
}
public HyperLogLogOperations<K, V> opsForHyperLogLog() {
if (hllOps == null) {
hllOps = new DefaultHyperLogLogOperations<>(this);
}
return hllOps;
}
RedisTemplate和StirngRedisTemplate就能利用这些方法对redis进行操作。下面来做个例子
在test测试类中添加一个方法,我们向redis中添加一些字符串。
package com.chtw.springboot02;
import com.chtw.config.Hello;
import com.chtw.entity.User;
import com.chtw.service.HelloService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import javax.sql.DataSource;
import java.sql.SQLException;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ApplicationTests {
@Autowired
DataSource dataSource;
@Autowired
HelloService helloService;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
RedisTemplate redisTemplate;
@Test
public void redisTemplatetest() {
stringRedisTemplate.opsForValue().append("message","hello world");
}
@Test
public void sys() throws SQLException {
System.out.println(dataSource.getClass());
System.out.println(dataSource.getConnection());
}
}
运行redisTemplatetest方法,再到redis里面去看:
就添加成功了,操作简单。下面我们在存放一个对象进去,你会发现它不是以json的新式存放的,redis的默认序列化机制没有将对象转化为json对象存放。redis默认的序列化机制是:jdk的序列化机制。
将方法改为如下后,重新运行测试方法:
@Test
public void redisTemplatetest() {
User user = helloService.getUserById(1);
redisTemplate.opsForList().leftPush("user",user);
//stringRedisTemplate.opsForValue().append("message","hello world");
}
在运行的过程中可能或出现如下错误:
这是因为我们的User对象不能被序列化,我们只需要在User实现Serializable:
然后再运行测试方法就可以了,运行结束后在到redis中看:
在实际开发工作中我们还是习惯将结果以json的形式将对象存储起来,下来具体看看序列化机制。
2. 序列化机制
在RedisAutoConfiguration中,给我们容器中添加了一个RedisTemplate,而在RedisTemplate中,有一个enableDefaultSerializer属性,它就是用来指定默认的序列化机制的。上面也看到默认使用的是JdkSerializationRedisSerializer这个序列化规则。
为了能够将对象序列化成json对象,我们也可以向容器中添加我们自己的序列化规则,写一个配置类,在里面添加我们自己的序列化规则就好了。
package com.chtw.config;
import com.chtw.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
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.*;
import java.net.UnknownHostException;
import java.time.Duration;
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, User> userRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, User> template = new RedisTemplate<Object, User>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<User> ser = new Jackson2JsonRedisSerializer<User>(User.class);
template.setDefaultSerializer(ser);
return template;
}
}
在测试类中添加如下方法:
@Autowired
RedisTemplate<Object, User> userRedisTemplate;
@Test
public void userRedisTemplatetest() {
User user = helloService.getUserById(1);
userRedisTemplate.opsForValue().set("user",user);
//stringRedisTemplate.opsForValue().append("message","hello world");
}
然后我们在去运行测试方法userRedisTemplatetest()这个时候就以json的形式保存了:
3. 自定义CacheManager
先再写一个实体类和相关查询方法:
JavaBean,People1类:
package com.chtw.entity;
/**
* @author CHTW
* @date 2019-11-05-16:06
*/
public class People1 implements Serializable{
private int id;
private String peoplename;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPeoplename() {
return peoplename;
}
public void setPeoplename(String peoplename) {
this.peoplename = peoplename;
}
}
//controller层
@ResponseBody
@GetMapping("/getpeid")
public People1 getpeById(int id){
return helloService.getPeopleById(id);
}
//service层
@Cacheable(value = "people",key="#id")
public People1 getPeopleById(int id){
People1 pList = peopleMapper.getPeopleById(id);
if(pList!=null) {
return pList;
}else{
return new People1();
}
}
//dao层
@Select("select * from people where id=#{id}")
public People1 getPeopleById(int id);
新建一个people数据表:
3.1 springboot 1.x自定义CacheManger
原理:引入了redis的starter,cacheManager变为 RedisCacheManager;
默认创建的 RedisCacheManager 操作redis的时候使用的是 RedisTemplate<Object, Object>
RedisTemplate<Object, Object> 是 默认使用jdk的序列化机制:JdkSerializationRedisSerializer。
所以我们要指定我们的序列化规则:Jackson2JsonRedisSerializer。
Spring Boot 底层创建RedisCacheManager的源码是
那么我也可以参照源码来自定义我们的CacheManager:
package com.chtw.config;
import com.chtw.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
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.*;
import java.net.UnknownHostException;
import java.time.Duration;
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, User> userRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, User> template = new RedisTemplate<Object, User>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<User> ser = new Jackson2JsonRedisSerializer<User>(User.class);
template.setDefaultSerializer(ser);
return template;
}
@Bean
public RedisCacheManager UserCacheManager(RedisTemplate<Object, User> userRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(userRedisTemplate);
//前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
}
如果存在多个实体类需要序列化的时候,那我们就要指定多个RedisTemplate和多个CacheManger:
package com.chtw.config;
import com.chtw.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
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.*;
import java.net.UnknownHostException;
import java.time.Duration;
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, User> userRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, User> template = new RedisTemplate<Object, User>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<User> ser = new Jackson2JsonRedisSerializer<User>(User.class);
template.setDefaultSerializer(ser);
return template;
}
@Bean
public RedisCacheManager UserCacheManager(RedisTemplate<Object, User> userRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(userRedisTemplate);
//前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
@Bean
public RedisTemplate<Object, People1> peopleRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, People1> template = new RedisTemplate<Object, People1>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<User> ser = new Jackson2JsonRedisSerializer<People1>(User.class);
template.setDefaultSerializer(ser);
return template;
}
@Bean
public RedisCacheManager PeopleCacheManager(RedisTemplate<Object, People1> peopleRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(peopleRedisTemplate);
//前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
}
然后再在每一个service层上通过cacheconfig指定CacheManager:
3.2 springboot 2.x自定义CacheManger
Spring Boot2.X 与Spring Boot1.X 有很大不同,Spring Boot2 底层源码是:
那我们也可以模仿这个来写我们的自定义的CacheManager:
package com.chtw.config;
import com.chtw.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
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.*;
import java.net.UnknownHostException;
import java.time.Duration;
@Configuration
public class MyRedisConfig {
@Primary //将某个缓存管理器作为默认的
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory){
RedisCacheConfiguration cacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(connectionFactory).cacheDefaults(cacheConfiguration).build();
}
}
这样写好后,然后运行项目,访问我们的查询接口,就可以看到,redis中就是以json的方式存放的数据了。
本节类容到此结束
本人联系方式2329095893,欢迎各位进行学习讨论
欢迎关注熊熊出没ING公众号,不定时跟新Java、python、信息安全等相关知识哦。