根據springboot對緩存的自動配置原理:
如果沒有工程中沒有引入其它的CacheManager,默認使用ConcurrentMapCacheManager;
ConcurrentMapCacheManager管理的緩存為ConcurrentMapCache;
ConcurrentMapCache利用ConcurrentHashMap來保存緩存數據;
1.安裝redis
使用Docker安裝;
查看redis鏡像名:
docker search redis
可以看到:
docker公共倉庫docker.hub中redis的鏡像名為docker.io/redis;
可以簡寫為redis;

從docker公共倉庫中拉取redis鏡像到本地:
docker pull redis
查看是否拉取成功
docker images
可以看到:
redis鏡像已經安裝到本地倉庫,版本是目前最新的latest

啟動redis:
docker run -d -p 6379:6379 --name myredis docker.io/redis
使用docker run命令啟動:
-d ->后台啟動
-p ->端口轉發,把docker容器的端口轉發到主機端口,否則不能訪問;redis默認監聽6379端口;
--name ->自定義的docker容器名;
后面接要啟動的docker鏡像名;
是否啟動成功:
docker ps
2.引入redis依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
3.配置redis
yml配置:
spring:
redis:
host: 192.168.1.193 #redis主機地址
4.使用RestTemplate操作redis
原理:
引入redis后,自動配置類RedisAutoConfiguration生效;
用@Bean注解給ioc容器中添加了兩個組件:RedisTemplate、StringRedisTemplate;

這兩個組件都是用來操作redis的;
RedisTemplate中的泛型<Object,Object>分別代表redis中的key和value;
由於往redis中操作字符串的場景較多,專門提供了StringRedisTemplate;
5. 使用StringRedidsTemplate給redis中插入一條字符串數據
@RunWith(SpringRunner.class) @SpringBootTest(classes = Cache01Application.class) public class TestRedis { @Autowired private StringRedisTemplate strTemp; @Test public void go(){ strTemp.opsForValue().append("gun", "M4-A1"); } }
結果:
使用redis可視化工具查看

6.使用RedisTemplate保存對象
踩坑:
實體類必需是可序列化的;
java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.example.demo.entity.Employee]
解決:
Employee實現Serializable接口;
測試類:
@RunWith(SpringRunner.class) @SpringBootTest(classes = Cache01Application.class) public class TestRedis { @Autowired(required = false) private EmployeeDao dao; @Autowired private RedisTemplate<Object, Object> temp; @Test public void go(){ Employee emp1 = dao.get(1); temp.opsForValue().set("emp", emp1); } }
結果:
對象被序列化成為二進制保持在redis中;
默認使用java自帶的序列化器;

7.以json的格式保存對象
兩種實現方式:
1】對象轉json字符串保存;(利用轉換工具,FastJson、Jackson等)
2】更換默認的序列化器;
1)更換序列化器
RedisTemplate默認使用jdk自帶序列化器;

更換序列化器:
定義一個配置類,利用@Bean向ioc容器注入一個RedisTemplate實例;
修該實例的默認序列化器;
原理:
redis的自動配置類中向ioc容器中注入RedisTemplate實例時使用了@ConditionalOnMissingBean(name = {"redisTemplate"}) ;
@Bean注入組件時默認方法名即為bean名;
可以用自己注入的RedisTemplate實例替換自動配置類注入的;
RedisTemplate的key和value都是用默認序列化器做序列號;
只需要替換掉默認序列化器即可;
配置類:
@Configuration public class RedisConfig { @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); //替換默認序列化器 Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class); template.setDefaultSerializer(serializer); return template; } }
測試類:
使用junit4測試
@RunWith(SpringRunner.class) @SpringBootTest(classes = Cache01Application.class) public class TestRedis { @Autowired(required = false) private EmployeeDao dao; @Autowired private RedisTemplate<Object, Object> temp; @Test public void go(){ Employee emp1 = dao.get(1); temp.opsForValue().set("emp", emp1); } }
結果:

8.注解式緩存
注解式緩存在沒有引入其它CacheManager時,默認使用CurrnetHashMap來保存數據;
引入redis后將會使用RedisCacheManager;
也就是說注解式緩存將使用Redis來保持數據;
dao:
使用@Cacheable標記get方法,當方法被調用時,會緩存方法的返回值
public interface EmployeeDao { @Cacheable(cacheNames = {"emp"}) public Employee get(Integer id); }
controller:
@RestController public class EmployeeController { @Autowired(required = false) //加required=false,防止報紅 private EmployeeDao dao; @RequestMapping("/get/{id}") public Employee get(@PathVariable("id") Integer id){ return dao.get(id); } }
測試:
瀏覽器請求get接口,將導致dao層的get方法被調用,緩存注解生效,redis中會添加一條數據;


由於默認使用jdk序列化器,redis中緩存的是二進制數據

1)以json格式緩存
原理:
緩存的自動配置類:CacheAutoConfiguration用注解@Import向ioc容器中注入Redis緩存配置類


RedisCacheConfiguration利用@Bean注解,向ioc容器中注入RedisCacheManager;
條件是:@ConditionalOnMissingBean({CacheManager.class})
RedisCacheManager默認使用jdk的序列化器來序列化key和value;因此redis中保存的是二進制;
為了用json序列化器,可以在容器中注入一個CacheManager,這樣自動注入的RedisCacheManager就不會生效;
新建一個配置類:
@Configuration public class RedisConfig { //使用json序列化器的RedisCacheManager @Bean public CacheManager cacheManager(RedisConnectionFactory factory){ RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofDays(1)) .disableCachingNullValues() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build(); } }
測試:
瀏覽器訪問


