redis客戶端Jedis使用小結(jié)
Redis的Java客戶端-Jedis
在Redis官網(wǎng)中提供了各種語(yǔ)言的客戶端,地址:https://redis.io/docs/clients/
其中Java客戶端也包含很多但在開(kāi)發(fā)中用的最多的還是Jedis,接下來(lái)就讓我們以Jedis開(kāi)始我們的快速實(shí)戰(zhàn)。
Jedis快速入門
入門案例詳細(xì)步驟
案例分析:
創(chuàng)建工程:
創(chuàng)建一個(gè)maven管理的java項(xiàng)目
引入依賴:
在pom.xml文件下添加以下依賴
<dependencies> <!--jedis--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.4.3</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>RELEASE</version> <scope>test</scope> </dependency> </dependencies>
建立連接
新建一個(gè)單元測(cè)試類,內(nèi)容如下:
private Jedis jedis; @BeforeEach void setUp() { // 1.建立連接 jedis = new Jedis("192.168.218.134", 6379); // jedis = JedisConnectionFactory.getJedis(); // 2.設(shè)置密碼 jedis.auth("123456"); // 3.選擇庫(kù) jedis.select(0); }
測(cè)試:
@Test void testString() { // 存入數(shù)據(jù) String result = jedis.set("name", "onenewcode"); System.out.println("result = " + result); // 獲取數(shù)據(jù) String name = jedis.get("name"); System.out.println("name = " + name); } @Test void testHash() { // 插入hash數(shù)據(jù) jedis.hset("user:1", "name", "Jack"); jedis.hset("user:1", "age", "21"); // 獲取 Map<String, String> map = jedis.hgetAll("user:1"); System.out.println(map); }
釋放資源
@AfterEach void tearDown() { if (jedis != null) { jedis.close(); } }
Jedis連接池
Jedis本身是線程不安全的,并且頻繁的創(chuàng)建和銷毀連接會(huì)有性能損耗,因此我們推薦大家使用Jedis連接池代替Jedis的直連方式
有關(guān)池化思想,并不僅僅是這里會(huì)使用,很多地方都有,比如說(shuō)我們的數(shù)據(jù)庫(kù)連接池,比如我們tomcat中的線程池,這些都是池化思想的體現(xiàn)。
創(chuàng)建Jedis的連接池
public class JedisConnectionFacotry { private static final JedisPool jedisPool; static { //配置連接池 JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(8); poolConfig.setMaxIdle(8); poolConfig.setMinIdle(0); poolConfig.setMaxWaitMillis(1000); //創(chuàng)建連接池對(duì)象 jedisPool = new JedisPool(poolConfig, "192.168.218.134",6379,1000,"123456"); } public static Jedis getJedis(){ return jedisPool.getResource(); } }
代碼說(shuō)明:
1) JedisConnectionFacotry:工廠設(shè)計(jì)模式是實(shí)際開(kāi)發(fā)中非常常用的一種設(shè)計(jì)模式,我們可以使用工廠,去降低代的耦合,比如Spring中的Bean的創(chuàng)建,就用到了工廠設(shè)計(jì)模式
2)靜態(tài)代碼塊:隨著類的加載而加載,確保只能執(zhí)行一次,我們?cè)诩虞d當(dāng)前工廠類的時(shí)候,就可以執(zhí)行static的操作完成對(duì) 連接池的初始化
3)最后提供返回連接池中連接的方法.
改造原始代碼
代碼說(shuō)明:
1.在我們完成了使用工廠設(shè)計(jì)模式來(lái)完成代碼的編寫之后,我們?cè)讷@得連接時(shí),就可以通過(guò)工廠來(lái)獲得。而不用直接去new對(duì)象,降低耦合,并且使用的還是連接池對(duì)象。
2.當(dāng)我們使用了連接池后,當(dāng)我們關(guān)閉連接其實(shí)并不是關(guān)閉,而是將Jedis還回連接池的。
@BeforeEach void setUp(){ //建立連接 /*jedis = new Jedis("127.0.0.1",6379);*/ jedis = JedisConnectionFacotry.getJedis(); //選擇庫(kù) jedis.select(0); } @AfterEach void tearDown() { if (jedis != null) { jedis.close(); } }
Redis的Java客戶端-SpringDataRedis
SpringData是Spring中數(shù)據(jù)操作的模塊,包含對(duì)各種數(shù)據(jù)庫(kù)的集成,其中對(duì)Redis的集成模塊就叫做SpringDataRedis,官網(wǎng)地址:https://spring.io/projects/spring-data-redis
- 提供了對(duì)不同Redis客戶端的整合(Lettuce和Jedis)
- 提供了RedisTemplate統(tǒng)一API來(lái)操作Redis
- 支持Redis的發(fā)布訂閱模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的響應(yīng)式編程
- 支持基于JDK.JSON.字符串.Spring對(duì)象的數(shù)據(jù)序列化及反序列化
- 支持基于Redis的JDKCollection實(shí)現(xiàn)
SpringDataRedis中提供了RedisTemplate工具類,其中封裝了各種對(duì)Redis的操作。并且將不同數(shù)據(jù)類型的操作API封裝到了不同的類型中:
快速入門
SpringBoot已經(jīng)提供了對(duì)SpringDataRedis的支持,使用非常簡(jiǎn),首先創(chuàng)建一個(gè)spring boot項(xiàng)目
導(dǎo)入pom坐標(biāo)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.onenewcode</groupId> <artifactId>MyRedis</artifactId> <version>0.0.1-SNAPSHOT</version> <name>MyRedis</name> <description>MyRedis</description> <properties> <java.version>17</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>3.0.2</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--redis依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--common-pool--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!--Jackson依賴--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </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> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>17</source> <target>17</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <mainClass>com.onenewcode.myredis.MyRedisApplication</mainClass> <skip>true</skip> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
配置文件
在application.yml文件下添加以下內(nèi)容
spring: data: redis: host: 192.168.218.134 port: 6379 password: 123456 lettuce: pool: max-active: 8 #最大連接 max-idle: 8 #最大空閑連接 min-idle: 0 #最小空閑連接 max-wait: 100ms #連接等待時(shí)間
測(cè)試代碼
@SpringBootTest class MyRedisApplicationTests { @Resource private RedisTemplate<String, Object> redisTemplate; @Test void testString() { // 寫入一條String數(shù)據(jù) redisTemplate.opsForValue().set("name", "onenewcode"); // 獲取string數(shù)據(jù) Object name = redisTemplate.opsForValue().get("name"); System.out.println("name = " + name); } }
貼心小提示:SpringDataJpa使用起來(lái)非常簡(jiǎn)單,記住如下幾個(gè)步驟即可
SpringDataRedis的使用步驟:
- 引入spring-boot-starter-data-redis依賴
- 在application.yml配置Redis信息
- 注入RedisTemplate
目錄結(jié)構(gòu)
數(shù)據(jù)序列化器
RedisTemplate可以接收任意Object作為值寫入Redis,只不過(guò)寫入前會(huì)把Object序列化為字節(jié)形式,默認(rèn)是采用JDK序列化,得到的結(jié)果是這樣的:
缺點(diǎn):
- 可讀性差
- 內(nèi)存占用較大
我們可以自定義RedisTemplate的序列化方式,代碼如下:
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){ // 創(chuàng)建RedisTemplate對(duì)象 RedisTemplate<String, Object> template = new RedisTemplate<>(); // 設(shè)置連接工廠 template.setConnectionFactory(connectionFactory); // 創(chuàng)建JSON序列化工具 GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(); // 設(shè)置Key的序列化 template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); // 設(shè)置Value的序列化 template.setValueSerializer(jsonRedisSerializer); template.setHashValueSerializer(jsonRedisSerializer); // 返回 return template; } }
這里采用了JSON序列化來(lái)代替默認(rèn)的JDK序列化方式。最終結(jié)果如圖:
整體可讀性有了很大提升,并且能將Java對(duì)象自動(dòng)的序列化為JSON字符串,并且查詢時(shí)能自動(dòng)把JSON反序列化為Java對(duì)象。不過(guò),其中記錄了序列化時(shí)對(duì)應(yīng)的class名稱,目的是為了查詢時(shí)實(shí)現(xiàn)自動(dòng)反序列化。這會(huì)帶來(lái)額外的內(nèi)存開(kāi)銷。
StringRedisTemplate
盡管JSON的序列化方式可以滿足我們的需求,但依然存在一些問(wèn)題,自動(dòng)進(jìn)行序列化時(shí)會(huì)負(fù)載多余的信息。
為了在反序列化時(shí)知道對(duì)象的類型,JSON序列化器會(huì)將類的class類型寫入json結(jié)果中,存入Redis,會(huì)帶來(lái)額外的內(nèi)存開(kāi)銷。
為了減少內(nèi)存的消耗,我們可以采用手動(dòng)序列化的方式,換句話說(shuō),就是不借助默認(rèn)的序列化器,而是我們自己來(lái)控制序列化的動(dòng)作,同時(shí),我們只采用String的序列化器,這樣,在存儲(chǔ)value時(shí),我們就不需要在內(nèi)存中就不用多存儲(chǔ)數(shù)據(jù),從而節(jié)約我們的內(nèi)存空間
這種用法比較普遍,因此SpringDataRedis就提供了RedisTemplate的子類:StringRedisTemplate,它的key和value的序列化方式默認(rèn)就是String方式。
省去了我們自定義RedisTemplate的序列化方式的步驟,而是直接使用:
@SpringBootTest class MyRedisApplicationTests { @Resource private RedisTemplate<String, Object> redisTemplate; @Autowired private StringRedisTemplate stringRedisTemplate; // JSON工具 private static final ObjectMapper mapper = new ObjectMapper(); @Test void testString() { // 寫入一條String數(shù)據(jù) redisTemplate.opsForValue().set("1", "onenewcode"); // 獲取string數(shù)據(jù) Object name = redisTemplate.opsForValue().get("name"); System.out.println("name = " + name); } @Test void testSaveUser() throws JsonProcessingException { // 創(chuàng)建對(duì)象 User user = new User("onenewcode", 21); // 手動(dòng)序列化 String json = mapper.writeValueAsString(user); // 寫入數(shù)據(jù) stringRedisTemplate.opsForValue().set("user:200", json); // 獲取數(shù)據(jù) String jsonUser = stringRedisTemplate.opsForValue().get("user:200"); // 手動(dòng)反序列化 User user1 = mapper.readValue(jsonUser, User.class); System.out.println("user1 = " + user1); } }
此時(shí)我們?cè)賮?lái)看一看存儲(chǔ)的數(shù)據(jù),小伙伴們就會(huì)發(fā)現(xiàn)那個(gè)class數(shù)據(jù)已經(jīng)不在了,節(jié)約了我們的空間~
最后小總結(jié):
RedisTemplate的兩種序列化實(shí)踐方案:
方案一:
- 自定義RedisTemplate
- 修改RedisTemplate的序列化器為GenericJackson2JsonRedisSerializer
方案二:
- 使用StringRedisTemplate
- 寫入Redis時(shí),手動(dòng)把對(duì)象序列化為JSON
- 讀取Redis時(shí),手動(dòng)把讀取到的JSON反序列化為對(duì)象
Hash結(jié)構(gòu)操作
在基礎(chǔ)篇的最后,咱們對(duì)Hash結(jié)構(gòu)操作一下,收一個(gè)小尾巴,這個(gè)代碼咱們就不再解釋啦
馬上就開(kāi)始新的篇章~~~進(jìn)入到我們的Redis實(shí)戰(zhàn)篇
@SpringBootTest class RedisStringTests { ··· @Test void testHash() { stringRedisTemplate.opsForHash().put("user:400", "name", "onenewcode"); stringRedisTemplate.opsForHash().put("user:400", "age", "21"); Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:400"); System.out.println("entries = " + entries); } }
項(xiàng)目倉(cāng)庫(kù)
https://github.com/onenewcode/MyRedis.git
到此這篇關(guān)于redis客戶端Jedis使用小結(jié)的文章就介紹到這了,更多相關(guān)redis客戶端Jedis使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot參數(shù)校驗(yàn)及分組校驗(yàn)的使用教程
在日常的開(kāi)發(fā)中,參數(shù)校驗(yàn)是非常重要的一個(gè)環(huán)節(jié),嚴(yán)格參數(shù)校驗(yàn)會(huì)減少很多出bug的概率,增加接口的安全性,下面這篇文章主要給大家介紹了關(guān)于Spring Boot參數(shù)校驗(yàn)及分組校驗(yàn)使用的相關(guān)資料,需要的朋友可以參考下2021-08-08Java實(shí)現(xiàn)訂單超時(shí)未支付自動(dòng)取消的8種方法總結(jié)
這篇文章主要為大家介紹了Java實(shí)現(xiàn)訂單超時(shí)未支付自動(dòng)取消功能的8種不同方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-08-08學(xué)習(xí)Java中的日期和時(shí)間處理及Java日歷小程序的編寫
這篇文章主要介紹了學(xué)習(xí)Java中的日期和時(shí)間處理及Java日歷小程序的編寫,這個(gè)日歷小程序僅用簡(jiǎn)單的算法實(shí)現(xiàn)沒(méi)有用到date類等,但是帶有圖形界面,需要的朋友可以參考下2016-02-02Java中的FileWriter用法詳解與實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了關(guān)于Java中FileWriter用法的相關(guān)資料,包括寫入字符數(shù)據(jù)到文件、字符數(shù)組和部分字符寫入、配合BufferedWriter使用等方法,同時(shí)也解釋了其與OutputStreamWriter,BufferedWriter的異同特性,適合簡(jiǎn)單的文件寫入操作,需要的朋友可以參考下2024-10-10Servlet關(guān)于RequestDispatcher的原理詳解
這篇文章主要介紹了Servlet關(guān)于RequestDispatcher的原理詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11MyBatis中使用分頁(yè)插件PageHelper實(shí)現(xiàn)分頁(yè)功能
分頁(yè)是經(jīng)常使用的功能,本文主要介紹了Mybatis中處理特殊SQL處理邏輯,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06Java實(shí)現(xiàn)上傳和下載功能(支持多個(gè)文件同時(shí)上傳)
這篇文章主要介紹了Java實(shí)現(xiàn)上傳和下載功能,支持多個(gè)文件同時(shí)上傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12Springboot基于enable模塊驅(qū)動(dòng)的實(shí)現(xiàn)
這篇文章主要介紹了Springboot基于enable模塊驅(qū)動(dòng)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)粒子跟隨效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)粒子跟隨效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08