最近在學習Spring Boot 2.x整合Redis,在這裏和你們分享一下,但願對你們有幫助。html
Redis 是開源免費高性能的key-value數據庫。有如下的優點(源於Redis官網http://www.redis.net.cn/):redis
性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。spring
豐富的數據類型 – Redis支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數據類型操做。數據庫
原子 – Redis的全部操做都是原子性的,意思就是要麼成功執行要麼失敗徹底不執行。單個操做是原子性的。多個操做也支持事務,即原子性,經過MULTI和EXEC指令包起來。緩存
豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過時等等特性。服務器
若是想了解更多關於Redis是什麼,能夠參考:Redis初識併發
爲何要使用Redis來自博客園【原創】分佈式之redis複習精講 ,這篇博文關於Redis的講解我以爲超讚,謝謝做者的耐心分享。app
我使用的Spring Boot版本是2.1.0,根據網上的一些舊的教程進行整合Redis 3.2的時候,會有許多地方有錯誤提示。這是由於Spring Boot 2.x作了一些修改,這些修改對使用而有沒有影響呢?咱們改怎麼整合呢?下面就進入正式的整合過程。分佈式
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency>
如今會提示Project build error: 'dependencies.dependency.version' for org.springframework.boot:spring-boot-starter-redis:jar is missing. 提示spring-boot-starter-redis:jar找不到。ide
這是由於Spring Boot 1.4以後再也不支持spring-boot-starter-redis,更換spring-boot-starter-data-redis以後就能夠了。若是你的pom文件報錯,請檢查是否將spring-boot-starter-redis 改爲了spring-boot-starter-data-redis。
Spring Boot 2.x要使用下面的依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
這是以前版本的配置文件:
# REDIS (RedisProperties) # Redis數據庫索引(默認爲0) spring.redis.database=0 # Redis服務器地址 spring.redis.host=127.0.0.1 # Redis服務器鏈接端口 spring.redis.port=6379 # Redis服務器鏈接密碼(默認爲空) spring.redis.password= # 鏈接池最大鏈接數(使用負值表示沒有限制) spring.redis.pool.max-active=8 # 鏈接池最大阻塞等待時間(使用負值表示沒有限制) spring.redis.pool.max-wait=-1 # 鏈接池中的最大空閒鏈接 spring.redis.pool.max-idle=8 # 鏈接池中的最小空閒鏈接 spring.redis.pool.min-idle=0 # 鏈接超時時間(毫秒) spring.redis.timeout=0
若是Spring Boot 2.x這麼配置,有錯誤提示 Property 'spring.redis.pool.max-active' is Deprecated: Use 'spring.redis.jedis.pool.max-idle' instead. 'spring.redis.pool.max-active'已經被棄用了,推薦使用'spring.redis.jedis.pool.max-idle'來代替。
這是由於在2.x中配置redis的鏈接池信息時,再也不使用spring.redis.pool的屬性,而是直接使用redis的lettuce或jedis客戶端來配置。如今的配置以下:
# REDIS (RedisProperties) # Redis數據庫索引(默認爲0) spring.redis.database=0 # Redis服務器地址 spring.redis.host=127.0.0.1 # Redis服務器鏈接端口 spring.redis.port=6379 # Redis服務器鏈接密碼(默認爲空) spring.redis.password= # 鏈接池最大鏈接數(使用負值表示沒有限制) spring.redis.jedis.pool.max-active=8 # 鏈接池最大阻塞等待時間(使用負值表示沒有限制) spring.redis.jedis.pool.max-wait=-1 # 鏈接池中的最大空閒鏈接 spring.redis.jedis.pool.max-idle=8 # 鏈接池中的最小空閒鏈接 spring.redis.jedis.pool.min-idle=0 # 鏈接超時時間(毫秒) spring.redis.timeout=0
這是以前的RedisConfig配置類:
@Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) { CacheManager cacheManager = new RedisCacheManager(redisTemplate); return cacheManager; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>(); redisTemplate.setConnectionFactory(factory); return redisTemplate; } }
如今這麼寫會有報錯The constructor RedisCacheManager(RedisTemplate<capture#1-of ?,capture#2-of ?>) is undefined。
這是由於Spring Boot 2.x版本刪除了RedisCacheManager這個構造器, 也不能夠經過以前的setDefaultExpiration方法設置默認的緩存過時時間等。
那麼要怎樣構造一個 RedisCacheManager?看看官方文檔中怎麼說?文檔地址:https://docs.spring.io/spring-data/data-redis/docs/2.1.x/reference/html/#new-in-2.1.0
官方文檔5.13.1. Support for the Spring Cache Abstraction(對Spring Cache Abstraction的支持)是關於怎麼配置緩存的說明,我嘗試着翻譯了一下(藍色部分),英文水平有限,各位輕噴。
Spring Redis provides an implementation for the Spring cache abstraction through the org.springframework.data.redis.cache package. To use Redis as a backing implementation, add RedisCacheManager to your configuration, as follows:
Spring Redis在 org.springframework.data.redis.cache 包中爲Spring緩存抽象提供了一個實現方案。要使用Redis做爲支持實現,須要將RedisCacheManager添加到配置中,以下所示:
@Bean public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { return RedisCacheManager.create(connectionFactory); }
RedisCacheManager behavior can be configured with RedisCacheManagerBuilder, letting you set the default RedisCacheConfiguration, transaction behavior, and predefined caches.
RedisCacheManager能夠用 RedisCacheManagerBuilder 進行配置,容許自定義設置默認的RedisCacheConfiguration、事務行爲和預約義的緩存。
RedisCacheManager cm = RedisCacheManager.builder(connectionFactory) .cacheDefaults(defaultCacheConfig()) .initialCacheConfigurations(singletonMap("predefined", defaultCacheConfig().disableCachingNullValues())) .transactionAware() .build();
As shown in the preceding example, RedisCacheManager allows definition of configurations on a per-cache basis.
正如上面的例子所示,RedisCacheManager 容許基於每一個緩存進行配置。
The behavior of RedisCache created with RedisCacheManager is defined with RedisCacheConfiguration. The configuration lets you set key expiration times, prefixes, and RedisSerializer implementations for converting to and from the binary storage format, as shown in the following example:
RedisCacheManager建立RedisCache的行爲被定義爲RedisCacheConfiguration。該配置容許設置鍵值過時時間、前綴和RedisSerializer實現等屬性,以便與二進制存儲格式進行轉換,以下所示:
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(1)) .disableCachingNullValues();
RedisCacheManager defaults to a lock-free RedisCacheWriter for reading and writing binary values. Lock-free caching improves throughput. The lack of entry locking can lead to overlapping, non-atomic commands for the putIfAbsent and clean methods, as those require multiple commands to be sent to Redis. The locking counterpart prevents command overlap by setting an explicit lock key and checking against presence of this key, which leads to additional requests and potential command wait times.
It is possible to opt in to the locking behavior as follows:
也能夠選擇鎖定行爲,以下所示:
RedisCacheManager cm = RedisCacheManager.build(RedisCacheWriter.lockingRedisCacheWriter())
.cacheDefaults(defaultCacheConfig())
...
By default, any key for a cache entry gets prefixed with the actual cache name followed by two colons. This behavior can be changed to a static as well as a computed prefix.
The following example shows how to set a static prefix:
如下示例顯示如何設置靜態前綴:
// static key prefix RedisCacheConfiguration.defaultCacheConfig().prefixKeysWith("( ͡° ᴥ ͡°)"); The following example shows how to set a computed prefix: // computed key prefix RedisCacheConfiguration.defaultCacheConfig().computePrefixWith(cacheName -> "¯\_(ツ)_/¯" + cacheName);
The following table lists the default settings for RedisCacheManager:
下表列出了RedisCacheManager的默認設置:
Setting
|
Value
|
Cache Writer
|
Non-locking
|
Cache Configuration
|
RedisCacheConfiguration#defaultConfiguration
|
Initial Caches
|
None
|
Trasaction Aware
|
No
|
The following table lists the default settings for RedisCacheConfiguration:
下表列出了RedisCacheConfiguration的默認設置:
Key Expiration
|
None
|
Cache null
|
Yes
|
Prefix Keys
|
Yes
|
Default Prefix
|
The actual cache name
|
Key Serializer
|
StringRedisSerializer
|
Value Serializer
|
JdkSerializationRedisSerializer
|
Conversion Service
|
DefaultFormattingConversionService with default cache key converters
|
對於Spring Boot 2.x,這裏我使用RedisCacheConfiguration簡單配置一下緩存時間,完成RedisCacheManager的配置,代碼以下:
@Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(1)); RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build(); return cacheManager; } }
在這裏僅建立一個簡單的RedisService,來進行存取緩存數據。
@Service public class RedisService { @Resource private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value) { //更改在redis裏面查看key編碼問題 RedisSerializer redisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); ValueOperations<String, Object> vo = redisTemplate.opsForValue(); vo.set(key, value); } public Object get(String key) { ValueOperations<String, Object> vo = redisTemplate.opsForValue(); return vo.get(key); } }
實體類沒有修改,和以前文章裏面用的同樣:
@Entity @Table(name = "user") public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; @Column(name = "username") private String userName; @Column(name = "password") private String passWord; public User() { super(); } public User(String userName, String passWord) { super(); this.userName = userName; this.passWord = passWord; } public User(Long id, String userName, String passWord) { super(); this.id = id; this.userName = userName; this.passWord = passWord; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } }
@RestController @RequestMapping("user") public class UserController { @Autowired private UserRepository userRepository; @Autowired private RedisService redisService; @RequestMapping("/saveUser") public String saveUser(Long id, String userName, String passWord) { User user = new User(id, userName, passWord); redisService.set(id + "", user); return "success"; } @RequestMapping("/getUserById") public User getUserById(Long id) { User res = (User) redisService.get(id + ""); return res; } }
使用Postman進行測試,訪問http://localhost:8080//user/saveUser?id=12&userName=Howard&passWord=magician,添加了一個User。
看看Redis數據庫,使用get key查看,獲得一個對象:
http://localhost:8080//user/getUserById?id=12,經過id獲取User。
這是過濾器和攔截器的日誌信息,能夠看到沒有進行MySQL數據庫的操做,直接從緩存中讀取,說明Redis配置生效了:
若是訪問以前的接口,是有操做數據庫的: