SpringBoot整合redis

redis是最經常使用的緩存數據庫,經常使用於存儲用戶登陸token、臨時數據、定時相關數據等。java

redis是單線程的,因此redis的操做是原子性的,這樣能夠保證不會出現併發問題。git

redis基於內存,速度很是快,據測試,redis讀的速度是110000次/s,寫的速度是81000次/sgithub

本節介紹SpringBoot引入redis,以及使用RedisTemplate來操做redis數據。web

採用SpringBoot 2.1.9.RELEASE,對應示例代碼在:https://github.com/laolunsi/spring-boot-examples/tree/master/07-spring-boot-redis-demoredis


1、A Simple Demo-使用SpringBoot鏈接redis

maven:spring

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

yml:數據庫

server:
  port: 8867
spring:
  redis:
    host: localhost
    port: 6379
    #password: ''
    database: 6

測試類:緩存

@SpringBootTest
@RunWith(SpringRunner.class)
public class RedisTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testRedis() {
        String key = "hello";
        redisTemplate.opsForValue().set("hello", "你好");

        String res = (String) redisTemplate.opsForValue().get(key);
        System.out.println(res);
    }
}

執行結果:springboot

file

看一下redis:併發

file

這裏存在一個問題:默認的存儲方式致使key在redis-manager裏面顯示出來是亂碼的,而且存儲結果是二進制了。這樣不利用咱們查看redis裏面的數據。

咱們須要自定義redis存儲的序列化規則。


2、解決RedisTemplate默認序列化的問題

完善一下maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

定義RedisConfig類:

/**
 * redis配置
 * 主要是配置Redis的序列化規則,替換默認的jdkSerializer
 * key的序列化規則用StringRedisSerializer
 * value的序列化規則用Jackson2JsonRedisSerializer
 */
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);

        // 使用Jackson2JsonRedisSerialize替換默認序列化
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        // 設置key和value的序列化規則
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

刪除以前的key,從新執行一下test方法:
file

下面來演示一下SpringBoot使用RedisTemplate進行redis數據的操做


3、基於SpringBoot的redis操做——key/list/hash

RedisTemplate內置redis操做以下:

file

這裏主要展現value/hash/list三種用法:


3.1 RedisTemplate.opsForValue

@Test
    public void testKeyOps() {
        // 測試redis操做key-value形式
        Set<String> keySet = new HashSet<>();

        String key1 = "name";
        keySet.add(key1);
        // 存儲簡單的key-value,並設置過時時間
        redisTemplate.opsForValue().set(key1, "eknown", 1, TimeUnit.MINUTES);

        String key2 = "token:user1";
        String key3 = "token:user2";
        keySet.add(key2);
        keySet.add(key3);
        //
        redisTemplate.opsForValue().set(key2, "{\"name\":\"eknown\"}, \"role\":\"admin\"");
        redisTemplate.opsForValue().set(key3, "{\"name\":\"test\"}, \"role\":\"test\"");

        // 根據key的集合獲取多個value
        List<String> valueList = redisTemplate.opsForValue().multiGet(keySet);
        for (String value : valueList) {
            System.out.println(value);
        }
    }

執行結果:

file

redis中的數據:

file

redis中的key顯示出了一個層級關係,這個小技巧對於實際項目有個很是好的做用:經過prefix:suffix這樣的形式,能夠將redis中存儲的數據分出層級。


3.2 RedisTemplate.opsForHash

清空該database下的數據,測試redisTemplate.opsForHash:

@Test
    public void testHashOps() {
        String key = "hash";
        // 單次往hash中存放一個數據
        redisTemplate.opsForHash().put(key, "1", "你好");

        Map<String, Object> map = new HashMap<>();
        map.put("2", "hello");
        map.put("3a", "china1=2");

        // 一次性向hash中存放一個map
        redisTemplate.opsForHash().putAll(key, map);

        // 獲取hash下的全部key和value
        Map<String, Object> resultMap = redisTemplate.opsForHash().entries(key);
        for (String hashKey : resultMap.keySet()) {
            System.out.println(hashKey + ": " + resultMap.get(hashKey));
        }
    }

執行結果:

file

redis:
file


3.3 RedisTemplate.opsForList

@Test
    public void testListOps() {
        String listKey = "list";
        redisTemplate.opsForList().leftPush(listKey, "first value"); // 從list最左邊插入數據
        redisTemplate.opsForList().leftPush(listKey, "second value but left");
        redisTemplate.opsForList().rightPush(listKey, 3); // 從list最右邊插入數據

        List<Object> list = new ArrayList<>();
        list.add("hello");
        list.add("http://www.eknown.cn");
        list.add(23344);
        list.add(false);
        redisTemplate.opsForList().rightPushAll(listKey, list); // 從list右邊批量插入數據

        long size = redisTemplate.opsForList().size(listKey);
        if (size > 0) {
            for (int i = 0; i < size -1 ; i++) {
                // 從list最左邊開始讀取list中的數據,注意pop會致使出棧,也就是數據被取出來了(redis中就沒有這個值了)
                // 此處咱們讀取size-1條數據,僅留下最後一條數據
                System.out.println(i + ":" + redisTemplate.opsForList().leftPop(listKey).toString());
            }
        }
    }

執行上面的腳本,注意在最後的讀取list數據代碼前面加一個斷點,此時redis中是這樣的:

file

放開斷點,程序繼續執行,控制檯以下:

file

注意,此時redis中僅剩餘最後一條數據,這是因爲pop的問題,list中的數據被讀取並刪除了:

file


好了,這一節主要講了SpringBoot引入redis,以及使用redis的一些基本操做和相關技巧,在此基礎上,咱們可讓咱們的項目變得更加快速、靈活!

相關文章
相關標籤/搜索