SpringBoot配置redis

創建SpringBoot項目:https://blog.csdn.net/weixin_41381863/article/details/106504682

引入相關依賴

<dependency>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter-data-redis</artifactId>
	    <!-- 這裏會根據引入的springboot版本自動選擇,也可單獨指定版本 -->
	    <!-- 最新版本查詢:https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
	    <!-- <version>2.3.0.RELEASE</version> -->
	</dependency>


<!-- 如果需要配置連接池,還需要以下依賴。不使用連接池則不需要 -->
<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

配置屬性

### redis配置 ###
spring.redis.host=127.0.0.1
spring.redis.port=6379
# 安裝的時候如果沒有設置密碼則沒有此項
spring.redis.password=123456
# 使用redis的哪一個庫,默認是0
spring.redis.database=0
# redis連接超時時間 單位毫秒
spring.redis.timeout=2000
# 連接池最大連接數(負值表示沒有限制,比如-1)
spring.redis.lettuce.pool.max-active=20
# 獲取連接最大阻塞等待時間(負值表示沒有限制,比如-1)
spring.redis.lettuce.pool.max-wait=-1
# 連接池中的最小空閒連接
spring.redis.lettuce.pool.min-idle=20
# 連接池中的最大空閒連接
spring.redis.lettuce.pool.max-idle=100
# springboot默認使用的redis連接是lettuce。
# 如果需要換成jedis需要額外引入jedis的依賴包。
# 並且使用下面的配置
 #spring.redis.jedis.pool.max-active=
### redis配置 ###

如果需要使用jedis,則加入以下的依賴包(最好是在spring-boot-starter-data-redis中將lettuce的依賴排除)。

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <!-- 最新版本查詢:https://mvnrepository.com/artifact/redis.clients/jedis/3.3.0 -->
    <version>3.3.0</version>
</dependency>

使用RedisTemplate操作redis

RedisTemplate是springboot-redis提供的一個操作redis的模板,它一個泛型類RedisTemplate<K, V>。注意,它是被默認裝配進Spring的IoC的,即我們可以直接使用@Autowired或@Resource使用它。除此之外,還提供了一個StringRedisTemplate來操作redis,同樣的,StringRedisTemplate也是被默認裝配進IoC的。這就是爲什麼,很多書籍或博客寫了配置RedisTemplate,而直接使用了StringRedisTemplate。其中,StringRedisTemplate繼承RedisTemplate<String, String>。按道理講,裝配了父類,卻直接注入子類,肯定是會報錯的(不知道你是否有思考過這個問題^_^)。這麼一來,如果只使用StringRedisTemplate,其實配置或者不配置RedisTemplate<K, V>都沒什麼實際意義。

接下來,慢慢道來爲什麼要配置RedisTemplate,以及StringRedisTemplate和RedisTemplate關係。

注意一:假如我們不配置RedisTemplate,而直接使用RedisTemplate。會導致我們存入redis的數據變成以下形式。

key:

value:

而直接使用StringRedisTemplate,又不會出現這種情況。

RedisTemplate使用的默認使用的序列化是JdkSerializationRedisSerializer<T>。StringRedisTemplate繼承了RedisTemplate,但是,在StringRedisTemplate的構造方法中,重新設置了序列化方式爲StringRedisSerializer。如下:

其中RedisSerializer.string()追蹤進去就是

除此之外,還支持很多序列化方式。所有的序列化方式必須實現RedisSerializer<T>接口。如下所示。其中,支持我們自定義序列化方式,還可以使用fastjson中的序列化方式。

注意二:在使用RedisTemplate<K, V>時。獲取RedisTemplate的bean時,其實是根據bean的名稱去找的(默認裝配的是一個泛型的bean)。所以是沒辦法按照類型去獲取bean的。

正確的的代碼:

@Autowired
private RedisTemplate<String, Object> redisTemplate;

錯誤的代碼:

@Autowired
private RedisTemplate<String, Object> redisTemplateObj;

 

關於使用RedisTemplate還是StringRedisTemplate。我是這麼認爲的,畢竟redis除了支持string還支持hash等其他數據類型。如果團隊要求,在存儲對象時,在代碼中先將其序列化爲json數據之後再進行存儲,那麼直接使用StringRedisTemplate即可。如果需要直接使用hash類型,且對象中帶有非Stirng類型的屬性,假如使用StringRedisTemplate,會出現類型轉換異常ClassCastException。通過上面的分析,StringRedisTemplate就是一個將序列化方式更改爲StringRedisSerializer的RedisTemplate。那麼,就需要老老實實的使用RedisTemplate。綜上,還是統一使用RedisTemplate比較好,操作類型比較豐富。

使用RedisTemplate時,爲了規避上述問題,就需要重新裝配RedisTemplate。

因爲序列化使用了FastJson。所以還需要引入FastJson的依賴包。

注意:一旦設置了序列化方式,不要萬不得已,不要更改。比如,存儲數據用了A序列化方式,獲取數據如果採用B序列化方式,會出現異常,導致獲取數據失敗。那麼,需要更改序列化方式,則需要清除redis全部數據。

<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<!-- 最新版本查詢:https://mvnrepository.com/artifact/com.alibaba/fastjson -->
			<version>1.2.70</version>
</dependency>
@Configuration
public class RedisConfig {

	@Autowired
	private RedisConnectionFactory redisConnectionFactory;
	
	@Bean(name = "redisTemplate")
	public RedisTemplate<String, Object> initRedisTemplate() {
		
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(redisConnectionFactory);
		// 支持事物
		redisTemplate.setEnableTransactionSupport(true);
		// key的序列化方式採用StringRedisSerializer。相信很少用對象作爲key的吧。
        // 如果要走非主流路線,將對象作爲key,且對象含有非String屬性,需要將key的序列化方式
        // 更改爲下面的value序列化方式
		StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
		redisTemplate.setKeySerializer(stringRedisSerializer);
		redisTemplate.setHashKeySerializer(stringRedisSerializer);
		
		// 設置value的序列化方式GenericFastJsonRedisSerializer(需要依賴fastjson)
		GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
		redisTemplate.setValueSerializer(fastJsonRedisSerializer);
		redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);

// 如果不想使用fastJson。常用的還有jackson的序列化方式。springboot項目中,默認帶了jackson。
//		Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
//		ObjectMapper objectMapper = new ObjectMapper();
//		objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//		objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//		jacksonSerializer.setObjectMapper(objectMapper);
//		redisTemplate.setValueSerializer(jacksonSerializer);
//		redisTemplate.setHashValueSerializer(jacksonSerializer);

		// 顧名思義,在屬性設置之後運行.初始化配置的作用
		redisTemplate.afterPropertiesSet();
		return redisTemplate;
	}
}

因爲這裏,我們重新裝配了RedisTemplate<String, Object>,指定了泛型。所以在注入RedisTemplate<String, Object>時,就可以按類型獲取了(獲取bean的時候,可以任意命名)。

至此,就完成了所有配置。然後可以愉快的玩耍了。

測試用例:

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

//	@Autowired
//	private StringRedisTemplate redisTemplate;
	
	@Autowired
	private RedisTemplate<String, Object> redisTemplateObj;
	
	@Test
	public void setStringTest() {
		redisTemplateObj.opsForValue().set("k1", "zepal");
		System.out.println("done");
	}
	
	@Test
	public void getStringTest() {
		String result = (String) redisTemplateObj.opsForValue().get("k1");
		System.out.println(result);
	}
	
	
	@Test
	public void setHashObjTest() {
		Map<String, Object> map = new HashMap<>();
		map.put("name", "zepal");
		map.put("gender", "男");
		map.put("age", 18);
		redisTemplateObj.opsForHash().putAll("h1", map);
		System.out.println("done");
	}
	
	@Test
	public void getHashObjTest() {
		String name = (String) redisTemplateObj.opsForHash().get("h1", "name");
		System.out.println(name);
	}
}

 

操作封裝

在開發中,如果每次操作RedisTemplate都需要調用它的api,比較麻煩,所以,可以簡單進行封裝一下。

@Service
public class CacheService {

	private RedisTemplate<String, Object> redisTemplate;
	
	/**
	 * <p>新增緩存:不帶超時策略
	 * */
	public void setCache(String key, String value) {
		redisTemplate.opsForValue().set(key, value);
	}
	
	/**
	 * <p>新增緩存:帶超時策略
	 * */
	public void setCache(String key, String value, 
			long timeOut, TimeUnit timeUnit) {
		redisTemplate.opsForValue().set(key, value, timeOut, timeUnit);
	}
	
	/**
	 * <p>獲取緩存
	 * */
	public String getCache(String key) {
		String value = (String) redisTemplate.opsForValue().get(key);
		return value;
	}
	
	/**
	 * <p>刪除緩存
	 * */
	public boolean deleteCache(String key) {
		Boolean isSuccess = redisTemplate.delete(key);
		return isSuccess;
	}
	
	// 還可以擴展其它...
	
}

 

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