文档章节

使用Spring + Jedis集成Redis

nick_chen
 nick_chen
发布于 2015/10/24 22:24
字数 1312
阅读 23873
收藏 59

一、集成环境

Tomcat7

JDK1.7

Jedis-2.7.2

Spring-4.1.6

二、资源依赖

(省略,网上很多)

三、集成过程

1、配置资源池

     这里使用Jedis的ShardedJedisPool来管理,我们定义该配置文件为:spring-redis.xml,全部内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:util="http://www.springframework.org/schema/util"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util-3.2.xsd">
 
  <!-- 引入jedis配置文件 -->
    <context:property-placeholder location="classpath:conf/properties/redis.properties"
    ignore-unresolvable="true" />
   
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal">
        <value>${redis.pool.maxActive}</value>
        </property>
        <property name="maxIdle">
         <value>${redis.pool.maxIdle}</value>
        </property>
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
    </bean>
   
     <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"  scope="singleton">
        <constructor-arg index="0" ref="jedisPoolConfig" />
        <constructor-arg index="1">
            <list>
                <bean class="redis.clients.jedis.JedisShardInfo">
                    <constructor-arg name="host" value="${redis.uri}" />
                </bean>
            </list>
        </constructor-arg>
    </bean>
</beans>

几个注意的点:

(1)如果你有多个数据源需要通过<context:property-placeholder管理,且不愿意放在一个配置文件里,那么一定要加上ignore-unresolvable=true"

(2)注意新版的(具体从哪个版本开始不清楚,有兴趣可以查一下)JedisPoolConfig的property name,不是maxActive而是maxTotal,而且没有maxWait属性,建议看一下Jedis源码。

(3)ShardedJedisPool有多种构造函数,选择你需要的(具体看源码),示例中只初始化了一个分片,并使用了通过指定host的构造器(具体格式见下文),如果有集群,在<list>下增加新的<bean>即可。

(4)当然,你的spring核心配置文件中得有<context:component-scan base-package="com.xxxx.xxx"/>扫描组件。


2、准备redis.properties,内容如下:

redis.pool.maxActive=200
redis.pool.maxIdle=50
redis.pool.minIdle=10
redis.pool.maxWaitMillis=20000
redis.pool.maxWait=300
redis.uri = redis://password@127.0.0.1:6379/0
redis.timeout=30000

这里要注意redis.uri的格式:redis://[密码]@[服务器地址]:[端口]/[db index]

建议大家使用这种方式,配置内容少,还能自定义db index,非常适合开发、测试和线上环境的切换


3、将spring-redis.xml加入web.xml的context中,如下:

 <context-param>
   
<param-name>contextConfigLocation</param-name>

    <param-value>classpath:conf/spring-redis.xml</param-value>

  </context-param>

如果你有多个数据源通过spring管理(如mysql),则同时加载,如下:

 <context-param>
   
<param-name>contextConfigLocation</param-name>
   
<param-value>classpath:conf/spring-mybatis.xml,classpath:conf/spring-redis.xml</param-value>

  </context-param>


3、以上所有的配置已完成,接下来的代码的实现

     (1)推荐大家使用统一的类来管理Jedis实例的生成和回收,参考代码如下:JedisDataSourceImpl.class

@Repository("jedisDS")
public class JedisDataSourceImpl implements JedisDataSource {
    private static final Logger LOG = LoggerFactory.getLogger(JedisDataSourceImpl.class);
    
    @Autowired
    private ShardedJedisPool shardedJedisPool;
    
    @Override
    public ShardedJedis getRedisClient() {
        ShardedJedis shardJedis = null;
        try {
            shardJedis = shardedJedisPool.getResource();
            return shardJedis;
        } catch (Exception e) {
            LOG.error("[JedisDS] getRedisClent error:" + e.getMessage());
            if (null != shardJedis)
                shardJedis.close();
        }
        return null;
    }

    @Override
    public void returnResource(ShardedJedis shardedJedis) {
        shardedJedis.close();
    }

    @Override
    public void returnResource(ShardedJedis shardedJedis, boolean broken) {
        shardedJedis.close();
    }

}

这里要注意的是Jedis实例的回收,从jedis2.6开始,原returnResource方式已经提示在后续版本中不再支持,所以不建议大家再用ShardedJedisPool里的returnResource和retureBrokenResource方法,虽然在2.7中还支持(毕竟是因为这两个方法存在漏洞)。

     (2)编写具体的Jedis操作类(片断):RedisClientTemplate.class

@Repository("redisClientTemplate")
public class RedisClientTemplate {
    private static final Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);

    @Autowired
    private JedisDataSource redisDataSource;

    public void disconnect() {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        shardedJedis.disconnect();
    }

    /**
     * 设置单个值
     * 
     * @param key
     * @param value
     * @return
     */
    public String set(String key, String value) {
        String result = null;

        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.set(key, value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    /**
     * 获取单个值
     * 
     * @param key
     * @return
     */
    public String get(String key) {
        String result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }

        boolean broken = false;
        try {
            result = shardedJedis.get(key);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    public Boolean exists(String key) {
        Boolean result = false;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.exists(key);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    public String type(String key) {
        String result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.type(key);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    /**
     * 在某段时间后失效
     * 
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(String key, int seconds) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.expire(key, seconds);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    /**
     * 在某个时间点失效
     * 
     * @param key
     * @param unixTime
     * @return
     */
    public Long expireAt(String key, long unixTime) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.expireAt(key, unixTime);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    public Long ttl(String key) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.ttl(key);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    public boolean setbit(String key, long offset, boolean value) {

        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean result = false;
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.setbit(key, offset, value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    public boolean getbit(String key, long offset) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean result = false;
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;

        try {
            result = shardedJedis.getbit(key, offset);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    public long setRange(String key, long offset, String value) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        long result = 0;
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.setrange(key, offset, value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    public String getRange(String key, long startOffset, long endOffset) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        String result = null;
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.getrange(key, startOffset, endOffset);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }
}

     (3)好了,接下来在你的业务代码里加载RedisClientTemplate.class就可以了。


© 著作权归作者所有

nick_chen
粉丝 10
博文 5
码字总数 3998
作品 0
大兴
架构师
私信 提问
加载中

评论(11)

Carvendy
Carvendy
不是有一个JedisCluster吗?
lixugood
lixugood
testOnBorrow=false 才可以
Skqing
Skqing
可以不分片吗
王胖
王胖
序列化有没有要注意的地方
s
sdust007
沙发
大海osc
大海osc
博客中有个错误,【这里要注意redis.uri的格式:redis://[密码]@[服务器地址]:[端口]/[db index]】
这里正确的写法应该是:

redis://:密码@服务器地址/端口号/[db index]

少了个冒号。
SpringBoot中文社区
SpringBoot中文社区
/**
   * 连接池
   * */
  private ShardedJedisPool shardedJedisPool;
  public RedisService(ShardedJedisPool shardedJedisPool){
    this.shardedJedisPool = shardedJedisPool;
  }
  /**
   * 回调函数
   * */
  private <T> T execute(Function<ShardedJedis ,T> fun){
     ShardedJedis shardedJedis = null;
try{
  // 获取Redis连接
  shardedJedis = shardedJedisPool.getResource();
  return fun.callback(shardedJedis);
}finally{
   //关闭连接
  if(shardedJedis != null){
    shardedJedis.close();
  }
}
  }
  /**
   * 添加数据到缓存
   * */
  public String set(final String key,final String value){
    return this.execute(new Function<ShardedJedis, String>() {
      public String callback(ShardedJedis jedis) {
        return jedis.set(key, value);
      }
    });
  }
  /**
   * 添加数据到缓存,并且设置生命周期值,单位为秒
   * */
  public String set(final String key,final String value,final Integer seconds){
    return this.execute(new Function<ShardedJedis, String>() {
      public String callback(ShardedJedis jed
Andyfoo
Andyfoo
纠正一个错误,url中的密码程序中按[用户名:密码]解析的,直接写密码会报错误,
redis://[密码]@[服务器地址]:[端口]/[db index]
正确的写法,多加一个冒号即可。
redis://:[密码]@[服务器地址]:[端口]/[db index]
t
tscnd3
找到原因了在JedisShardInfo 构造函数 多了一个 password
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg name="host" value="127.0.0.1" />
<constructor-arg name="port" value="6379" />
<constructor-arg name="timeout" value="50000" />

<constructor-arg name="password" value="123456"/>
</bean>
t
tscnd3
请问为什么 我的为什么报这个错误

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redis.clients.jedis.JedisShardInfo#4a6ef07c' defined in file [F:\workspace\tscnd\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\app-webplat\WEB-INF\classes\cfg\spring\spring-config.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
Spring Boot 2.X(六):Spring Boot 集成 Redis

Redis 简介 什么是 Redis Redis 是目前使用的非常广泛的免费开源内存数据库,是一个高性能的 key-value 数据库。 Redis 与其他 key-value 缓存(如 Memcached )相比有以下三个特点: 1.Redis...

朝雾轻寒
10/27
0
0
Spring集成Redis方案(spring-data-redis)(基于Jedis的单机模式)(待实践)

说明:请注意Spring Data Redis的版本以及Spring的版本!最新版本的Spring Data Redis已经去除Jedis的依赖包,需要自行引入,这个是个坑点。并且会与一些低版本的Spring有冲突,要看官方文档...

easonjim
2017/10/05
0
0
SpringBoot整合Redis Lettuce

最近在准备集成的基础框架使用Spring Boot2搭建,其中Redis的支持不仅仅是丰富了它的API,更是替换掉底层Jedis的依赖,取而代之换成了Lettuce(生菜) jedis跟lettuce的区别 Lettuce 和 Jedis ...

lemonLove
2018/12/12
1K
0
SpringBoot2.0 快速集成 Jedis客户端 连接 redis 服务

SpringBoot2.0 快速集成 Jedis客户端 连接 redis 服务 1.简单介绍 redis 2.自动配置方式集成Jedis客户端 2.1引入Jedis依赖 2.2 定义 Jedis Properties类 2.3 定义 Jedis客户端自动配置类 3....

小红牛
06/24
0
0
使用Spring Data Redis操作Redis(单机版)

说明:请注意Spring Data Redis的版本以及Spring的版本!最新版本的Spring Data Redis已经去除Jedis的依赖包,需要自行引入,这个是个坑点。并且会与一些低版本的Spring有冲突,要看官方文档...

easonjim
2017/11/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java注解合并,注解继承

spring中有时候一个类上面标记很多注解。 实际上Java注解可以进行继承(也就是把多个注解合并成1个) 比如说SpringMVC的注解 @RestController@RequestMapping("/person") 可以合并为一个 @P...

物种起源-达尔文
18分钟前
4
0
撤消Git中一个文件的工作副本修改?

在最后一次提交之后,我修改了工作副本中的一堆文件,但是我想撤消对这些文件之一的更改,例如将其重置为与最新提交相同的状态。 但是,我只想撤消仅一个文件的工作副本更改,而没有其他操作...

技术盛宴
54分钟前
4
0
Qt编写气体安全管理系统28-模拟工具

一、前言 模拟工具在一些涉及到硬件通信的程序中特别有用,也特别需要,回顾这十年来做过的项目,95%的项目都是软硬件交互的,貌似软硬件结合的项目更有生命力一些,纯软件的或者纯硬件的,并...

飞扬青云
今天
4
0
关于生活方式

生活就是生活,但难免和工作混在一起,所以要建立自己的生活方式,把工作稍微隔开点。 首先呢,每周放假的两天肯定会: 洗衣服,收拾屋子,列计划是必须要做的事情。 (这里可能还包含一些处...

T型人才追梦者
今天
6
0
JVM

一、JVM一些基本概念 1、JVM和普通虚拟机 JVM:Java Virtual Machine,程序自己独立的运行环境;堆栈、寄存器、字节码指令;可以运行多种语言:Java、Scala、Grovvy; 普通虚拟机:能完整提供...

请把小熊还给我_m
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部