SpringBoot2.0學習筆記:Spring Boot中集成Redis

一、關於Lettuce

在SpringBoot2.0.x版本中集成Redis,Lettuce現已取代Jedis作爲Redis驅動。那Lettuce又是個什麼呢?與Jedis又有何區別呢?

Lettuce 是一個可伸縮的線程安全的 Redis 客戶端,支持同步、異步和響應式模式。多個線程可以共享一個連接實例,而不必擔心多線程併發問題。它基於優秀 Netty NIO 框架構建,支持 Redis 的高級功能,如 Sentinel,集羣,流水線,自動重新連接和 Redis 數據模型

Jedis在實現上是直接連接的redis server,如果在多線程環境下是非線程安全的,這個時候只有使用連接池,爲每個Jedis實例增加物理連接 Lettuce的連接是基於Netty的,連接實例(StatefulRedisConnection)可以在多個線程間併發訪問,應爲StatefulRedisConnection是線程安全的,所以一個連接實例(StatefulRedisConnection)就可以滿足多線程環境下的併發訪問,當然這個也是可伸縮的設計,一個連接實例不夠的情況也可以按需增加連接實例。
 


二、SpringBoot集成Redis實操

POM依賴 本地下載JAR包好慢啊,這網太破了。

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
    </dependencies>

配置文件中配置與redis有關的屬性

spring.redis.host=192.168.159.128
spring.redis.port=6379
spring.redis.password=redis
#連接超時時間(毫秒)
spring.redis.timeout=10000ms
# 連接池最大連接數(使用負值表示沒有限制) 默認 8
spring.redis.lettuce.pool.max-active=16
# 連接池中的最大空閒連接 默認 8
spring.redis.lettuce.pool.max-idle=8
# 連接池最大阻塞等待時間,單位毫秒(使用負值表示沒有限制) 默認 -1
spring.redis.lettuce.pool.max-wait=1000ms
# 連接池中的最小空閒連接 默認 0
spring.redis.lettuce.pool.min-idle=0
spring.redis.lettuce.shutdown-timeout=100ms

2、 redis配置

接下來我們需要配置redis的key跟value的序列化方式,默認使用的JdkSerializationRedisSerializer 這樣的會導致我們通過redis desktop manager顯示的我們key跟value的時候顯示不是正常字符。 所以我們需要手動配置一下序列化方式 新建一個config包,在其下新建一個RedisConfiguration.java 具體代碼如下

package com.wang.redis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfiguration {

    /**
     * 配置自定義redisTemplate
     * @return
     */
    @Bean
    RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

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

        template.setValueSerializer(serializer);
        //使用StringRedisSerializer來序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }
}

其中@Configuration 代表這個類是一個配置類,然後@AutoConfigureAfter(RedisAutoConfiguration.class) 是讓我們這個配置類在內置的配置類之後在配置,這樣就保證我們的配置類生效,並且不會被覆蓋配置。其中需要注意的就是方法名一定要叫redisTemplate 因爲@Bean註解是根據方法名配置這個bean的name的。

3、測試

我們需要測試在redis緩存對象的用例,所以我們需要新建一個實體類。
代碼如下:

package com.wang.redis;
import com.wang.redis.entry.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest
public class RedisTest {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void redisTest() {
        // redis存儲數據
        String key = "redis_name_wangchao_01";
        redisTemplate.opsForValue().set(key, "wangchao");
        // 獲取數據
        String value = (String) redisTemplate.opsForValue().get(key);
        System.out.println("獲取redis中key爲" + key + "的值爲:" + value);

        //User user =User.builder().id(1L).username("wangchao").age(19).sex(1).build();
        User user = new User();
        user.setUsername("wangchao");
        user.setSex(18);
        user.setId(1L);

        String userKey = "edis_name_wangchao_"+user.getId();
        redisTemplate.opsForValue().set(userKey, user);
        User newUser = (User) redisTemplate.opsForValue().get(userKey);
        System.out.println("獲取redis中key爲" + userKey + "的User值爲:" + newUser);
    }
}

測試通過。OK

備註:對象序列化過程中,User對象構建方式不一致,導致結果出現差異。

# 使用Lombok註解 @Builder,需顯示增加對象的無參構造器獲取使用Lombok的無參構造註解。
User user =User.builder().id(1L).username("wangchao").age(19).sex(1).build();
User user = new User();

在User.builder().id(1L).username("wangchao").age(19).sex(1).build();方式,是使用Lombok註解生成構建者模式。若對象沒有添加無參構造器,則對象會在反序列化過程中報錯。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章