您好,登錄后才能下訂單哦!
@[toc]
redis是一個高性能的key-value數據庫
性能強,適合高度的讀寫操作(讀的速度是110000次/s,寫的速度是81000次/s )。
支持較為豐富的數據類型(如二進制的Strings, Lists, Hashes, Sets ,Ordered Sets)
注:redis的單線程僅僅是說在網絡請求這一模塊上用一個請求處理客戶端的請求,但比如說持久化它就會重開一個線程/進程去進行處理。
點擊鏈接 下載 redis 的 window 版,下載好后,放入你平時放軟件的位置,解壓出來即安裝完成。(需要注意的是放入的文件目錄,當前用戶要是可讀可寫的權限,比如window下的C:\Program Files (x86),這個目錄默認只有管理員權限才能讀寫,redis運行時要在該目錄下實時寫入日志文件的,若無權限讀寫,則會操作不成功)
解壓出來的目錄如下所示,因為是Windows端的,可雙擊exe文件開啟客戶端,服務端。
因為這是 springboot 整合 redis 系列,所以雙擊打開服務端即可,別關閉打開的 cmd 窗口。
在pom.xml中加入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在application.properties中添加
# Redis
#Redis服務器地址
spring.redis.host=127.0.0.1
#Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認為空)
spring.redis.password=
#Redis數據庫索引(默認為0)
spring.redis.database=0
#連接池最大連接數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=50
#連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=3000
#連接池中的最大空閑連接
spring.redis.jedis.pool.max-idle=20
#連接池中的最小空閑連接
spring.redis.jedis.pool.min-idle=5
#連接超時時間(毫秒)
spring.redis.timeout=4000
新增代碼后的目錄如下所示
這里先說明一下主要類的作用,Springboot 提供了 RedisTemplate 類來操作 Redis,但是該類既無注釋解釋,命名規律也不夠 “望文生義” 。 所以寫了個 RedisUtil 來封裝一些常用的方法, RedisConfig 主要是將默認的自動注入改為手動注入并加入序列化,避免一些中文亂碼問題。
這里特別說一說 RedisUtil 類,搜索 springboot 和 redis 的文章,這個需要自己封裝的類網上大多寫的非常混亂,而且前后的封裝邏輯不一致, 我估計是某位博主從至少三個人那里復制粘貼糅合起來的,然后大家都跟著這位博主復制粘貼,反而成了熱門文章。我猜測大家看它是個工具類,而且六百行左右,大多沒有仔細琢磨,能簡單測試通過即可,但是稍加思考,發現問題真的不少,很容易誤導那些喜歡 “拿來主義” 的 “萌新” 。
雖然我這個系列也是快速上手系列,但我理解的快速上手,就是把讓人云里霧里的概念講直白,然后先暫時跳過那些需要深入的,避免剛入手的畏難情緒,把整個操作流程寫的清楚明白,給別人講一千遍道一萬句,不如讓他對著現成的程序跑一遍,我一直認為:對著一片空白的屏幕學習程序,只會讓人愈加焦慮,最好的辦法是一邊運行,一邊深入。
所以我選取了 redis 五大類型中的String,Hash,Set,List,幾乎覆蓋每個類型,而 SortedSet 沒有選取是因為這是有序的Set,可以自己類比。工具類我統一提供的是取值,添加值,刪除值,命名規律絕對可以讓你 “望文生義” ,其實還有很多方法,這里我不全寫出來,是因為五大數據類型都有一堆方法,你不一定用得上,而且很占篇幅,在這里,授人以魚不如授人以漁,你仔細看看 RedisUtil 的工具類,就會發現規律,比如操作String,大多是先調用opsForValue()方法,操作Hash,大多先調用opsForHash()方法,把項目代碼下載到本地,idea里面點進去,就能看到相關的一堆方法。工具類只是重新調用了,換了個名字,加了些邏輯處理。
別看是熱門文章就盲從,我舉幾個剛才說的問題,
還有這個的注釋說明風格也不統一,給人的感覺看著容易云里霧里的,網上的工具類還用的都是這一個,真的是哭笑不得,大家抄來抄去,都是方案整合商,就不要……
下面開始代碼示范
RedisController.java
package com.example.controller;
import com.example.service.IRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("redis")
public class RedisController {
@Autowired
private IRedisService redisService;
@RequestMapping("/redisString")
public void redisString() {
this.redisService.redisString();
}
@RequestMapping("/redisHash")
public void redisHash() {
this.redisService.redisHash();
}
@RequestMapping("/redisSet")
public void redisSet() {
this.redisService.redisSet();
}
@RequestMapping("/redisList")
public void redisList() {
this.redisService.redisList();
}
@RequestMapping("/redisSortedSet")
public void redisSortedSet() {
//有序的set,故而省略
}
}
IRedisService.java
package com.example.service;
public interface IRedisService {
void redisString();
void redisHash();
void redisSet();
void redisList();
void redisSortedSet();
}
RedisServiceIml.java
package com.example.service;
import com.example.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
@Service("redisService")
public class RedisServiceIml implements IRedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Resource
private RedisUtil redisUtil;
public void redisString() {
//添加值
redisUtil.stringSet("AAA", "這是一個String類型的值");
//取值
Object value = redisUtil.stringGet("AAA");
System.out.println(value);
}
public void redisHash() {
//添加值
redisUtil.hashSet("BBB", "test1", "原hash值1");
redisUtil.hashSet("BBB", "test2", "新hash值1");
redisUtil.hashSet("BBB", "test1", "原hash值2");
redisUtil.hashSet("BBB", "test2", "新hash值2");
//取值
Object value1 = redisUtil.hashGet("BBB", "test1");
Object value2 = redisUtil.hashGet("BBB", "test2");
System.out.println(value1);
System.out.println(value2);
}
public void redisSet() {
//添值
redisUtil.setSet("CCC", "這是一組Set集合的第一個");
redisUtil.setSet("CCC", "這是一組Set集合的第二個");
redisUtil.setSet("CCC", "這是一組Set集合的第三個");
//取值
Set vaule = redisUtil.setGet("CCC");
System.out.println(vaule);
}
public void redisList() {
//添加值
redisUtil.listSet("DDD", "這是一組List集合的第一個");
redisUtil.listSet("DDD", "這是一組List集合的第二個");
redisUtil.listSet("DDD", "這是一組List集合的第三個");
//取值
List list = redisUtil.listGet("DDD", 0, -1);
System.out.println(list);
}
public void redisSortedSet() {
//有序的set,故而省略
}
}
RedisConfig.java
package com.example.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
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.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置連接工廠
template.setConnectionFactory(factory);
//序列化和反序列化redis中的值
Jackson2JsonRedisSerializer jackson = new Jackson2JsonRedisSerializer(Object.class);
//Java對象轉換成JSON結構
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化輸入的類型
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson.setObjectMapper(objectMapper);
// 值采用json序列化
template.setValueSerializer(jackson);
//使用StringRedisSerializer來序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
// 設置hash key和value序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson);
template.afterPropertiesSet();
return template;
}
}
RedisUtil.java
package com.example.util;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
//===============緩存相關方法===============
//指定緩存失效時間
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//根據key獲取過期時間,返回0代表為永久有效
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
//===============數據類型為String的相關方法===============
//根據key值獲取緩存值
public Object stringGet(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
//根據key值存入數據類型為String的緩存值
public boolean stringSet(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//根據key值存入數據類型為String的緩存值并設置時間
public boolean stringSetWithTime(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//刪除緩存
public void stringDelete(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
//===============數據類型為Hash的相關方法===============
//根據key和item獲取緩存值
public Object hashGet(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
//根據key和item存入數據類型為Hash的緩存值
public boolean hashSet(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//根據key和item存入數據類型為Hash的緩存值并設置時間
public boolean hashSetWithTime(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//刪除緩存
public void hashDelete(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
//===============數據類型為SET的相關方法===============
//根據key值獲取緩存值
public Set<Object> setGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//根據key值存入數據類型為SET的緩存值
public long setSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//根據key值存入數據類型為SET的緩存值并設置時間
public long setSetWithTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//刪除緩存
public long setDelete(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============數據類型為LIST的相關方法===============
//獲取List緩存的內容,從start到end,若從0到-1代表所有值
public List<Object> listGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//根據key值存入數據類型為List的緩存值
public boolean listSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//根據key值存入數據類型為List的緩存值并設置時間
public boolean listSetWithTime(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//刪除緩存
public long listDelete(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}
啟動項目后,瀏覽器輸入 http://localhost:8080/redis/redisString ,(前臺會報錯,是因為這個請求只是觸發后臺的業務邏輯,沒有前臺頁面展示)操作 String 類型的效果圖如下所示;
啟動項目后,瀏覽器輸入 http://localhost:8080/redis/redisHash ,操作 Hash 類型的效果圖如下所示;(注意一下,我之前代碼寫的是插入了四個值,只打印出來兩個,是因為如果key值和item值一樣,新來的值會覆蓋原來的值,對比圖和代碼,你品,你細品。)
啟動項目后,瀏覽器輸入 http://localhost:8080/redis/redisSet ,操作 Set 類型的效果圖如下所示;(Set是無序的)
啟動項目后,瀏覽器輸入 http://localhost:8080/redis/redisList ,操作 List 類型的效果圖如下所示;
注:如果是根據本文系列文章來的,因為一開始就配置好了spring security,所以記得將該地址配給所登錄的用戶。或者開一個超級管理員賬號,可以訪問項目的任意目錄,使用該管理員賬號訪問這些地址。
這是該學習系列的所有代碼,如果有不明白的,想自己實操豐富其中內容的,可以下載到本地,
GitHub , 碼云
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。