欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring-data-redis連接操作redis的實現(xiàn)

 更新時間:2021年07月14日 11:11:14   作者:雪水  
spring-data-redis則是對Jedis進行了高度封裝,使用起來非常方便。本文主要介紹了spring-data-redis連接操作redis的實現(xiàn),感興趣的可以了解一下

Java連接redis的客戶端有很多,其中比較常用的是Jedis. (參考:redis client)

spring-data-redis則是對Jedis進行了高度封裝,使用起來非常方便。下面就以代碼為例說明spring-data-redis的使用。

整個項目使用maven管理jar包,pom文件如下:

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 
 <groupId>com.snow</groupId>
 <artifactId>redis-test</artifactId>
 <version>0.0.1</version>
 <packaging>jar</packaging>
 
 <name>redis-test</name>
 <url>http://maven.apache.org</url>
 
 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <spring.version>4.3.2.RELEASE</spring.version>
  <slf4j.version>1.7.12</slf4j.version>
  <log4j.version>1.2.17</log4j.version>
  <junit.version>4.12</junit.version>
  <spring-data-redis.version>1.7.2.RELEASE</spring-data-redis.version>
 </properties>
 
 <dependencies>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${spring.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>${spring.version}</version>
   <scope>test</scope>
  </dependency>
 
  <dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>2.5.0</version>
   <type>jar</type>
  </dependency>
  <dependency>
   <groupId>org.springframework.data</groupId>
   <artifactId>spring-data-redis</artifactId>
   <version>${spring-data-redis.version}</version>
   <type>jar</type>
  </dependency>
 
  <!-- log -->
  <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>${log4j.version}</version>
  </dependency>
  <dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-log4j12</artifactId>
   <version>${slf4j.version}</version>
  </dependency>
  <dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>${slf4j.version}</version>
  </dependency>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>${junit.version}</version>
   <scope>test</scope>
  </dependency>
 </dependencies>
</project>

主要用到的jia包是spring-context、spring-data-redis、jedis以及日志打印相關(guān)的三個jar包

配置spring-data-redis如下application-context-redis.xml:

    <!-- 配置方法見 //www.dbjr.com.cn/database/201311/254449.html -->
 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
   <property name="maxTotal" value="500"/> <!-- 控制一個pool可分配多少個jedis實例 --> 
   <property name="maxIdle" value="100"/><!-- 最大能夠保持idel狀態(tài)的對象數(shù) -->
   <property name="maxWaitMillis" value="1000"/><!-- 表示當(dāng)borrow一個jedis實例時,最大的等待時間,如果超過等待時間,則直接拋出JedisConnectionException --> 
   <property name="timeBetweenEvictionRunsMillis" value="30000"/><!-- 多長時間檢查一次連接池中空閑的連接 -->
   <property name="minEvictableIdleTimeMillis" value="30000"/><!-- 空閑連接多長時間后會被收回, 單位是毫秒 -->
   <property name="testOnBorrow" value="true"/> <!-- 當(dāng)調(diào)用borrow Object方法時,是否進行有效性檢查 -->
   <property name="testOnReturn" value="true"/> <!-- 當(dāng)調(diào)用return Object方法時,是否進行有效性檢查 -->
   <property name="testWhileIdle" value="true"/>
 </bean>
      
   <span style="white-space:pre"> </span><!-- 直連master -->
 <bean id="jedisConnectionFactory"
  class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
  <constructor-arg ref="jedisPoolConfig" />
  <property name="hostName" value="${redis.hostName}" />
  <property name="port" value="${redis.port}" />
  <!-- <property name="password" value ="${redis.password}" /> -->
 </bean> 
    
    <span style="white-space:pre"> </span><bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" > 
     <span style="white-space:pre"> </span><property name="connectionFactory" ref="jedisConnectionFactory" />  
    <span style="white-space:pre"> </span></bean>

在配置文件中先配置一個連接池,然后配置一個connection工廠,最后配置bean redisTemplate,我們使用的class是StringRedisTemplate,從而決定我們后面的操作key及value都必須是String類型的。而通常我們希望將一個對象存入到redis中,這個時候可以將對象轉(zhuǎn)為json字符串之后再存儲,取出來的時候再將json字符串轉(zhuǎn)換為對象。這種操作還是比較方便的,都有線程的jar包。除了StringRedisTemplate之外,我們還可以使用RedisTemplate類,這里暫不介紹。

在application-context-redis.xml這個配置文件中還需要用到redis的host和port信息,我們可以配置一個文件properties文件如下:redis.properties

redis.hostName=127.0.0.1
redis.port=6379

這個配置文件需要在application-contex.xml中加載,同時application-context.xml還需要加載application-context-redis.xml配置文件

 <bean id="dbPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="ignoreUnresolvablePlaceholders" value="true" />
  <property name="locations">
   <list>
    <value>classpath:redis.properties</value>
   </list>
  </property>
  <property name="fileEncoding" value="UTF-8" /><!-- 資源文件的編碼 -->
 </bean> 
 <import resource="classpath:application-context-redis.xml" />  

接下來可以寫個redis操作的接口

public interface RedisService { 
    public void setStr(String key, String value);    
    public String getStr(String key);    
    public void rPushList(String key, String value);
    public String lPopList(String key); 
    public void delKey(String key); 
}

接口實現(xiàn)如下:

@Service(value = "redisService")
public class RedisServiceImpl extends AbstractRedisDao<String, String> implements RedisService {
 
    @Override
    public void setStr(String key, String value) {
        getRedisTemplate().opsForValue().set(key, value);
    }
 
    @Override
    public String getStr(String key) {
        return getRedisTemplate().opsForValue().get(key);
    }
 
    @Override
    public void rPushList(String key, String value) {
        getRedisTemplate().opsForList().rightPush(key, value);
 
    }
 
    @Override
    public String lPopList(String key) {
        return getRedisTemplate().opsForList().leftPop(key);
    }
    
    @Override
    public void delKey(String key) {
        getRedisTemplate().delete(key);
    }
}

在該實現(xiàn)中繼承了一個AbstractRedisDao,這個主要是提供getRedisTemplate()函數(shù),使我們能夠調(diào)用在application-context-redis.xml中配置的redisTemplate bean實例

public abstract class AbstractRedisDao<K, V> {
 
    @Autowired
    protected RedisTemplate<K, V> redisTemplate;
 
    // 設(shè)置redisTemplate
    public void setRedisTemplate(RedisTemplate<K, V> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
 
    public RedisTemplate<K, V> getRedisTemplate() {
        return redisTemplate;
    }
}

主要的程序都已經(jīng)寫完了,接下來可以用Junit寫個單元測試對接口測試下。

public class RedisServiceTest extends AbstractUnitTest {
    private static final Logger logger = LoggerFactory.getLogger(RedisServiceTest.class);
 
    @Resource
    private RedisService redisService;
 
    @Test
    public void testSetStr() {
        String key = "test";
        String value = "valuetest";
        redisService.setStr(key, value);
    }
 
    @Test
    public void testGetStr() {
        String key = "test";
        String value = redisService.getStr(key);
        logger.info("The value is {}", value);
    }
 
    @Test
    public void testRPushList() {
        String key = "list";
        for (int i = 0; i < 10; i++) {
            redisService.rPushList(key, String.valueOf(i));
        }
    }
       
    @Test
    public void testLPopList() {
        String key = "list";
        
        for(int i = 0; i < 9; i++) {
            String value = redisService.lPopList(key);
            logger.info("lpop value is {}", value);
        }
    }
    
    @Test
    public void testDelKey() {
        String key = "list";
        redisService.delKey(key);
    } 
}

在這個測試類中,為了能夠運行這些測試函數(shù),需要對所有的bean進行實例化,這個過程是在 AbstractUnitTest中實現(xiàn)的,代碼如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application-context.xml"})
public abstract class AbstractUnitTest {
    private static final Logger logger = LoggerFactory.getLogger(AbstractUnitTest.class);
 
//    @Test
//    public void stub() {
//        logger.info("msg from abstract unit test, just ignore this.");
//    }
 
    @After
    public void teardown() throws InterruptedException {
        logger.info("unit test complete.");
        TimeUnit.MILLISECONDS.sleep(500);// 因為有些測試是需要異步插入操作記錄的,sleep一下等待線程結(jié)束
    } 
}

AbstractUnitTest類可以作為測試spring的一個通用類。

主要的代碼就這些了,運行下可以看到結(jié)果是沒有問題的。下面我摘抄一段打印輸出說明一個問題:

016-08-02 20:43:16,608 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,609 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,610  INFO RedisServiceTest:54 - lpop value is 0
2016-08-02 20:43:16,610 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,611 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,611  INFO RedisServiceTest:54 - lpop value is 1
2016-08-02 20:43:16,611 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,611 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,612  INFO RedisServiceTest:54 - lpop value is 2
2016-08-02 20:43:16,612 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,612 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,612  INFO RedisServiceTest:54 - lpop value is 3
2016-08-02 20:43:16,612 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,613 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,613  INFO RedisServiceTest:54 - lpop value is 4
2016-08-02 20:43:16,613 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,613 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,613  INFO RedisServiceTest:54 - lpop value is 5
2016-08-02 20:43:16,613 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,614 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,614  INFO RedisServiceTest:54 - lpop value is 6
2016-08-02 20:43:16,614 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,614 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,618  INFO RedisServiceTest:54 - lpop value is 7
2016-08-02 20:43:16,618 DEBUG RedisConnectionUtils:125 - Opening RedisConnection
2016-08-02 20:43:16,618 DEBUG RedisConnectionUtils:205 - Closing Redis Connection
2016-08-02 20:43:16,618  INFO RedisServiceTest:54 - lpop value is 8
2016-08-02 20:43:16,618  INFO AbstractUnitTest:34 - unit test complete.

這段輸出是運行testLPopList得到的,這里面opening RedisConnection進行了9次,然后又Closing Redis Connection 9次,這是不是說每次執(zhí)行redis操作都需要創(chuàng)建一個連接,操作完然后又關(guān)閉連接呢?實際上不是這樣的,閱讀源代碼我們可以發(fā)現(xiàn)我們對redis的所有操作都是通過回調(diào)execute函數(shù)執(zhí)行的,其代碼如下:

public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {
    return execute(action, exposeConnection, false);
}
// execute實現(xiàn)如下:
// org.springframework.data.redis.core.RedisTemplate<K, V> --- 最終實現(xiàn)
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
    Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
    Assert.notNull(action, "Callback object must not be null");
    RedisConnectionFactory factory = getConnectionFactory();
    RedisConnection conn = null;
    try {
        if (enableTransactionSupport) {
            // only bind resources in case of potential transaction synchronization
            conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
        } else {
            conn = RedisConnectionUtils.getConnection(factory);
        }
        boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
        RedisConnection connToUse = preProcessConnection(conn, existingConnection);
        boolean pipelineStatus = connToUse.isPipelined();
        if (pipeline && !pipelineStatus) {
            connToUse.openPipeline();
        }
        RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
        T result = action.doInRedis(connToExpose);
        // close pipeline
        if (pipeline && !pipelineStatus) {
            connToUse.closePipeline();
        }
        // TODO: any other connection processing?
        return postProcessResult(result, connToUse, existingConnection);
    } finally {
        if (!enableTransactionSupport) {
            RedisConnectionUtils.releaseConnection(conn, factory);
        }
    }
}

這里面每次執(zhí)行action.doInRedis(connToExpose)前都要調(diào)用RedisConnectionUtils.getConnection(factory);獲得一個連接,進入RedisConnnectionUtils類中,getConnection(factory)最終調(diào)用的是doGetConnection(factory, true, false, enableTranactionSupport)這個函數(shù)。這個函數(shù)我們可以看下api文檔,發(fā)現(xiàn)實際上并不是真的創(chuàng)建一個新的redis連接,它只是在connectFactory中獲取一個連接,也就是從連接池中取出一個連接。當(dāng)然如果connectFactory沒有連接可用,此時如果allowCreate=true便會創(chuàng)建出一個新的連接,并且加入到connectFactory中。
基本上可以確定真實的情況是spring-data-redis已經(jīng)幫我們封裝了連接池管理,我們只需要調(diào)用一系列操作函數(shù)即可,這給操作redis帶來了極大的方便。

最后附上本文源代碼:redis-test

到此這篇關(guān)于spring-data-redis連接操作redis的實現(xiàn)的文章就介紹到這了,更多相關(guān)spring-data-redis連接操作redis內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中使用JWT的實戰(zhàn)

    SpringBoot中使用JWT的實戰(zhàn)

    本文主要介紹了SpringBoot中使用JWT的實戰(zhàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java詳解swagger2如何配置使用

    Java詳解swagger2如何配置使用

    編寫和維護接口文檔是每個程序員的職責(zé),根據(jù)Swagger2可以快速幫助我們編寫最新的API接口文檔,再也不用擔(dān)心開會前仍忙于整理各種資料了,間接提升了團隊開發(fā)的溝通效率
    2022-06-06
  • Java Elastic Job動態(tài)添加任務(wù)實現(xiàn)過程解析

    Java Elastic Job動態(tài)添加任務(wù)實現(xiàn)過程解析

    這篇文章主要介紹了Java Elastic Job動態(tài)添加任務(wù)實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • IDEA新手必備之各種快捷鍵詳解

    IDEA新手必備之各種快捷鍵詳解

    這篇文章主要介紹了IDEA新手必備之各種快捷鍵詳解,文中有非常詳細的快捷鍵介紹,對正在使用IDEA的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • 一文帶你搞懂Java中線程的創(chuàng)建方式

    一文帶你搞懂Java中線程的創(chuàng)建方式

    這篇文章主要為大家詳細介紹了Java中線程的創(chuàng)建方式的相關(guān)知識,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以了解一下
    2023-03-03
  • Java判斷一個時間是否在當(dāng)前時間區(qū)間代碼示例

    Java判斷一個時間是否在當(dāng)前時間區(qū)間代碼示例

    這篇文章主要給大家介紹了關(guān)于使用Java判斷一個時間是否在當(dāng)前時間區(qū)間的相關(guān)資料,在日常開發(fā)中我們經(jīng)常會涉及到時間的大小比較或者是判斷某個時間是否在某個時間段內(nèi),需要的朋友可以參考下
    2023-07-07
  • Spring中xml配置文件的基礎(chǔ)使用方式詳解

    Spring中xml配置文件的基礎(chǔ)使用方式詳解

    這篇文章主要介紹了Spring中xml配置文件的基礎(chǔ)使用方式,主要包括xml配置文件的讀取,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • Spring針對AOP詳細講解

    Spring針對AOP詳細講解

    Spring是一個廣泛應(yīng)用的框架,SpringAOP則是Spring提供的一個標(biāo)準(zhǔn)易用的aop框架,依托Spring的IOC容器,提供了極強的AOP擴展增強能力,對項目開發(fā)提供了極大地便利
    2022-06-06
  • Java中通過jsch來連接遠程服務(wù)器執(zhí)行l(wèi)inux命令

    Java中通過jsch來連接遠程服務(wù)器執(zhí)行l(wèi)inux命令

    這篇文章主要介紹了Java中通過jsch來連接遠程服務(wù)器執(zhí)行l(wèi)inux命令的相關(guān)資料,需要的朋友可以參考下
    2016-03-03
  • Springboot打包部署修改配置文件的方法

    Springboot打包部署修改配置文件的方法

    這篇文章主要介紹了Springboot打包部署修改配置文件的方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09

最新評論