微信公衆號:一個優秀的廢人。如有問題,請後臺留言,反正我也不會聽。
前言
兩個月沒更新原創了,實在慚愧。沒有藉口,就是因爲自己懶了。最近看了「刻意學習」,這本書談的是學習與行動的關係,書中提到了「持續行動」 這個概念,意思就是:我們要去實實在在地去做一些事情,而且是每天都做,才能稱之爲「持續行動」。看完這本書以後,我意識到我必須要做些什麼,那就是寫作。
Redis 簡介
Redis 是一個開源的,基於內存的鍵值數據存儲,用作數據庫,緩存和消息代理。在實現方面,Key-Value 存儲代表 NoSQL 空間中最大和最老的成員之一。Redis 支持數據結構,如字符串,散列,列表,集和帶範圍查詢的有序集。
在 spring data redis 的框架,可以很容易地編寫,通過提供一個抽象的數據存儲使用 Redis 的鍵值存儲的 Spring 應用程序。
非關係型數據庫,基於內存,存取數據的速度不是關係型數據庫所能比擬的
redis 是鍵值對 (key-value) 的數據庫
數據類型
- 字符串類型 string
- 散列類型 hash
- 列表類型 list
- 集合類型 set
- 有序集合類型 zset
其中,因爲SpringBoot 約定大於配置的特點,只要我們加入了 spring-data-redis 依賴包並配置 Redis 數據庫,SpringBoot 就會幫我們自動配置一個 RedisTemplate ,利用它我們就可以按照以下方式操作對應的數據類型,在下面實戰中我將會對這五種數據進行操作。
- redisTemplate.opsForValue(); //操作字符串
- redisTemplate.opsForHash(); //操作hash
- redisTemplate.opsForList(); //操作list
- redisTemplate.opsForSet(); //操作set
- redisTemplate.opsForZSet(); //操作有序set
開發環境
- SpringBoot 2.1.6 RELEASE
- spring-data-redis 2.1.9 RELEASE
- Redis 3.2
- IDEA
- JDK8
- mysql
關於如何安裝 Redis 這裏不再贅述,請自行搜索引擎搜索解決。
pom 依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=true
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update #ddl-auto:設爲 create 表示每次都重新建表
show-sql: true
redis:
host: localhost
port: 6379
# Redis數據庫索引(默認爲0)
database: 1
jedis:
pool:
#連接池最大連接數
max-active: 8
#最小空閒連接
min-idle: 0
#最大阻塞等待時間,負值表示沒有限制
max-wait: -1ms
#最大空閒連接
max-idle: 8
#連接超時時間(毫秒)
timeout: 20ms
# 無密碼可不寫
# password:
爲什麼亂碼?
/**
* 添加字符串
*/
@Test
public void setString(){
redisTemplate.opsForValue().set(USERKEY,"nasus");
redisTemplate.opsForValue().set(AGEKEY,24);
redisTemplate.opsForValue().set(CITYKEY,"清遠");
}
首先是添加字符串類型的數據。它的運行結果如下:
如何解決亂碼
我們可以看到插入的數據是亂碼的,這是因爲 SpringBoot 自動配置的這個 RedisTemplate 是沒有設置數據讀取時的 key 及 value 的序列化方式的。所以,我們要寫一個自己的 RedisTemplate 並設置 key 及 value 的序列化方式纔可以正常操作 Redis。如下:
@Configuration
public class RedisConfig {
private final RedisTemplate redisTemplate;
@Autowired
public RedisConfig(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Bean
@SuppressWarnings("unchecked")
public RedisTemplate<String, Object> redisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
//RedisSerializer<Object> jsonString = new GenericToStringSerializer<>(Object.class);
RedisSerializer<Object> jsonString = new FastJsonRedisSerializer<>(Object.class);
// String 的 key 和 hash 的 key 都採用 String 的序列化方式
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
// value 都採用 fastjson 的序列化方式
redisTemplate.setValueSerializer(jsonString);
redisTemplate.setHashValueSerializer(jsonString);
return redisTemplate;
}
}
這時,再次運行上面的單元測試,結果就正常了。
操作 List
/**
* 添加、獲取LIST
*/
@Test
public void setList(){
List<Student> students = studentService.findStudentList();
log.info("students size = {}", students.size());
//循環向 studentList 左添加值
students.forEach(value->redisTemplate.opsForList().leftPush(LISTKEY,value));
//向 studentList 右添加值
Student student = new Student();
student.setId(10);
student.setAge(24);
student.setName("rightPush");
redisTemplate.opsForList().rightPush(LISTKEY,student);
// 獲取值
log.info("studentList->{}",redisTemplate.opsForList().range(LISTKEY,0,10));
}
這裏需要說一下,leftpush 和 rightpush 的區別,前者是在 key 對應 list 的頭部添加元素,也就是我們常說的後來居上,List<Student> 下標最大的元素在這個 list 裏面處於第一位;而後者則是 在 key 對應 list 的尾部添加元素,剛好和前者相反。
獲取值,代碼這裏獲取的是 0 到 10 行的數據,控制檯打印結果:
[{"name":"優秀","id":9,"age":22}, {"name":"馮某華","id":8,"age":25}, {"name":"藍某城","id":7,"age":25}, {"name":"優秀","id":6,"age":22}, {"name":"馮某華","id":5,"age":25}, {"name":"藍某城","id":4,"age":25}, {"name":"馮某華","id":3,"age":25}, {"name":"藍某城","id":2,"age":25}, {"name":"廢人","id":1,"age":22}, {"name":"rightPush","id":10,"age":24}]
添加 List 結果:
這裏注意 1 到 9 行的 id 值剛好是相反的,而正常情況下,我從 mysql 數據中查出來的值是這樣的:
因此,驗證了 leftpush 和 rightpush 的區別。
操作 set
/**
* 添加和獲取Set
*/
@Test
public void setAndGetSet(){
List<String> usernameList = new ArrayList<>();
usernameList.add("nasus");
usernameList.add("nasus");
usernameList.add("一個優秀的廢人");
//循環向添加值
usernameList.forEach(value->redisTemplate.opsForSet().add(SETKEY,value));
log.info("取出usernameSet->{}",redisTemplate.opsForSet().members(SETKEY));
}
/**
* 刪除 Set
*/
@Test
public void delSet(){
redisTemplate.opsForSet().remove(SETKEY,"nasus");
}
Redis 的 set 數據結構跟 java 的 hashset 數據結構一樣,也是無序且不重複。所以我代碼裏 add 了兩個 nasus 字符串,其實只 add 了一個 nasus 。結果如下:
操作 hash
分別作了 hash 的添加、刪除以及獲取,代碼如下:這裏需要說明一下的是,hash 的 hash 有兩個鍵可以設置,其中第一個是 redis 中的鍵,而第二個是具體每條數據的 hashkey。
/**
* 添加 hash
*/
@Test
public void setHash(){
List<Student> students = studentService.findStudentList();
//添加
for (Student student : students){
redisTemplate.opsForHash().put(HASHKEY, student.getId().toString(), student);
}
}
/**
* 刪除 hash
*/
@Test
public void delHash(){
Student student = studentService.findStudentById(0);
// 刪除
redisTemplate.opsForHash().delete(HASHKEY,JSON.toJSONString(student));
}
/**
* 獲取 Hash
*/
@Test
public void getHash(){
List<Student> students = redisTemplate.opsForHash().values(HASHKEY);
log.info("values = {}", students);
}
添加 hash 操作結果:
獲取 hash 操作結果:
源碼地址
https://github.com/turoDog/Demo/tree/master/springboot_redis_demo
推薦閱讀
後語
如果本文對你哪怕有一丁點幫助,請幫忙點好看。你的好看是我堅持寫作的動力。
另外,關注之後在發送 1024 可領取免費學習資料。
資料詳情請看這篇舊文:Python、C++、Java、Linux、Go、前端、算法資料分享