springboot使用redis做緩存


根據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();
    }
}
 
測試:
    瀏覽器訪問
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM