iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >spring-data-redis连接操作redis的实现方法
  • 880
分享到

spring-data-redis连接操作redis的实现方法

2023-06-20 15:06:51 880人浏览 泡泡鱼
摘要

本篇内容介绍了“spring-data-redis连接操作Redis的实现方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Java连接re

本篇内容介绍了“spring-data-redis连接操作Redis的实现方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

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以及日志打印相关的三个jar包

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

<!-- 配置方法见 //www.yisu.com/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状态的对象数 -->   <property name="maxWaitMillis" value="1000"/><!-- 表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException -->    <property name="timeBetweenEvictionRunsMillis" value="30000"/><!-- 多长时间检查一次连接池中空闲的连接 -->   <property name="minEvictableIdleTimeMillis" value="30000"/><!-- 空闲连接多长时间后会被收回, 单位是毫秒 -->   <property name="testOnBorrow" value="true"/> <!-- 当调用borrow Object方法时,是否进行有效性检查 -->   <property name="testOnReturn" value="true"/> <!-- 当调用return Object方法时,是否进行有效性检查 -->   <property name="testWhileIdle" value="true"/> </bean>         <span > </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 > </span><bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" >      <span > </span><property name="connectionFactory" ref="jedisConnectionFactory" />      <span > </span></bean>

在配置文件中先配置一个连接池,然后配置一个connection工厂,最后配置bean redisTemplate,我们使用的class是StringRedisTemplate,从而决定我们后面的操作key及value都必须是String类型的。而通常我们希望将一个对象存入到redis中,这个时候可以将对象转为JSON字符串之后再存储,取出来的时候再将json字符串转换为对象。这种操作还是比较方便的,都有线程的jar包。除了StringRedisTemplate之外,我们还可以使用RedisTemplate类,这里暂不介绍。

在application-context-redis.xml这个配置文件中还需要用到redis的host和port信息,我们可以配置一个文件properties文件如下:redis.properties

redis.hostName=127.0.0.1redis.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); }

接口实现如下:

@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);    }}

在该实现中继承了一个AbstractRedisDao,这个主要是提供getRedisTemplate()函数,使我们能够调用在application-context-redis.xml中配置的redisTemplate bean实例

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

主要的程序都已经写完了,接下来可以用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);    } }

在这个测试类中,为了能够运行这些测试函数,需要对所有的bean进行实例化,这个过程是在 AbstractUnitTest中实现的,代码如下:

@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一下等待线程结束    } }

AbstractUnitTest类可以作为测试spring的一个通用类。

主要的代码就这些了,运行下可以看到结果是没有问题的。下面我摘抄一段打印输出说明一个问题:

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次,这是不是说每次执行redis操作都需要创建一个连接,操作完然后又关闭连接呢?实际上不是这样的,阅读源代码我们可以发现我们对redis的所有操作都是通过回调execute函数执行的,其代码如下:

public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {    return execute(action, exposeConnection, false);}// execute实现如下:// org.springframework.data.redis.core.RedisTemplate<K, V> --- 最终实现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);        }    }}

这里面每次执行action.doInRedis(connToExpose)前都要调用RedisConnectionUtils.getConnection(factory);获得一个连接,进入RedisConnnectionUtils类中,getConnection(factory)最终调用的是doGetConnection(factory, true, false, enableTranactionSupport)这个函数。这个函数我们可以看下api文档,发现实际上并不是真的创建一个新的redis连接,它只是在connectFactory中获取一个连接,也就是从连接池中取出一个连接。当然如果connectFactory没有连接可用,此时如果allowCreate=true便会创建出一个新的连接,并且加入到connectFactory中。
基本上可以确定真实的情况是spring-data-redis已经帮我们封装了连接池管理,我们只需要调用一系列操作函数即可,这给操作redis带来了极大的方便。

“spring-data-redis连接操作redis的实现方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: spring-data-redis连接操作redis的实现方法

本文链接: https://www.lsjlt.com/news/298028.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作