文档章节

Spring与Redis整合

-奋斗小青年-
 -奋斗小青年-
发布于 2016/01/19 22:41
字数 1383
阅读 152
收藏 1

参考博文:http://my.oschina.net/ydsakyclguozi/blog/465859?fromerr=WuJmq97D

  1. Redis版本redis-2.8.17

  2. Redis与spring整合所需的jar包:jedis.jar

  3. 修改spring配置文件:


  4.  <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">  
            <property name="maxActive"  value="600" />  
            <property name="maxIdle" value="300" />  
            <property name="maxWait" value="2000" /> 
            <property name="testOnBorrow"  value="true"/>  
        </bean>       
       <bean id="jedisShardInfo" class="redis.clients.jedis.JedisShardInfo" >  
            <constructor-arg name="host" value="127.0.0.1" />  
            <constructor-arg name="port" value="6379" type="int"/>  
           <constructor-arg name="timeout" value="60000" /> 
        </bean>        
        <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" >  
            <constructor-arg index="0" ref="jedisPoolConfig" />        
            <constructor-arg index="1">  
                <list>  
                    <ref bean="jedisShardInfo" />  
                </list>  
            </constructor-arg>  
        </bean>

    5、由于在配置spring扫描注解包时没有配置工具包的扫描,所以要在非spring容器的bean中使用到spring容器中已经初始化好的bean,现提供一个工具类:ServiceLocator

  5. package com.ncut.sunshy.util;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    public class ServiceLocator implements BeanFactoryAware {
        private static BeanFactory beanFactory = null;
     
        private static ServiceLocator servlocator = null;
     
        public void setBeanFactory(BeanFactory factory) throws BeansException {
        this.beanFactory = factory;
        }
     
        public BeanFactory getBeanFactory() {
        return beanFactory;
        }
     
        public static ServiceLocator getInstance() {
        if (servlocator == null)
            servlocator = (ServiceLocator) beanFactory.getBean("serviceLocator");
        return servlocator;
        }
        /**
         * 根据提供的bean名称得到相应的服务类
         * 
         * @param servName
         *            bean名称
         */
        public static Object getService(String servName) {
        return beanFactory.getBean(servName);
        }
    }

修改spring配置文件:

 <!-- 实现spring容器外的类实例获取spring容器里的、启动时初始化好的bean -->
    <bean id="serviceLocator" class="com.ncut.sunshy.util.ServiceLocator" scope="singleton" />

6、Redis操作工具类:JedisUtil

public class JedisUtil {
//获取redis服务器链接池对象,此bean是spring容器管理,所以借助工具从容器中获取bean,
//定义为static final,是因为这个连接池要使用于多线程;
private static final  ShardedJedisPool shardedJedisPool = 
(ShardedJedisPool)ServiceLocator.getService("shardedJedisPool");
  //从Redis服务器取储数据
    public static  Corpus getObject(String word) {
        //ShardedJedisPool shardedJedisPool = (ShardedJedisPool) ServiceLocator.getService("shardedJedisPool");//获取redis服务器链接;
        ShardedJedis jedis = shardedJedisPool.getResource();
        byte[] corpus = jedis.get(word.getBytes());
        if(jedis != null){
            shardedJedisPool.returnResource(jedis);
            //由于使用的是连接池,所以使用完链接记得还回去,
            //防止高并发下,链接不够用,从连接池获取不到链接而出现异常
        }
        
        return (Corpus) SerializeUtil.unserialize(corpus);

        }
    //向Redis服务器存储数据
    public static  void setObject(Corpus corpus) {
        //ShardedJedisPool shardedJedisPool = (ShardedJedisPool) ServiceLocator.getService("shardedJedisPool");//获取redis服务器链接;
        ShardedJedis jedis = shardedJedisPool.getResource();
         if(jedis != null){
                shardedJedisPool.returnResource(jedis);
            }
        jedis.set((corpus.getWord()).getBytes(), SerializeUtil.serialize(corpus));

        }
    //从Redis服务器删除数据
    public static  void delOject(String word){
        //ShardedJedisPool shardedJedisPool = (ShardedJedisPool) ServiceLocator.getService("shardedJedisPool");//获取redis服务器链接;
        ShardedJedis jedis = shardedJedisPool.getResource();
        boolean isExist=jedis.exists(word.getBytes());
        if(isExist){
            System.out.println("delete the key"+word);
            jedis.del(word);
        }
        if(jedis != null){
            shardedJedisPool.returnResource(jedis);
        }
    }
 
 }
 
 7、调用:
 Corpus cur = new Corpus();         
 cur = HashMapCachedTool.getObject(str);


8、贴一下使用过程中遇到的异常

jedis多线程异常

多线程下使用jedis会报一些奇怪的错误:

redis.clients.jedis.exceptions.JedisConnectionException: Unknown reply: t
        at redis.clients.jedis.Protocol.process(Protocol.java:72)
        at redis.clients.jedis.Protocol.read(Protocol.java:123)
        at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:183)
        at redis.clients.jedis.Connection.getMultiBulkReply(Connection.java:165)
        at redis.clients.jedis.Jedis.hgetAll(Jedis.java:863)
    redis.clients.jedis.exceptions.JedisConnectionException: Unknown reply: s
        at redis.clients.jedis.Protocol.process(Protocol.java:72)
        at redis.clients.jedis.Protocol.read(Protocol.java:123)
        at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:183)
        at redis.clients.jedis.Connection.getMultiBulkReply(Connection.java:165)
        at redis.clients.jedis.Jedis.hgetAll(Jedis.java:863)
    java.lang.ClassCastException: [B cannot be cast to java.util.List
        at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:183)
        at redis.clients.jedis.Connection.getMultiBulkReply(Connection.java:165)
        at redis.clients.jedis.Jedis.hgetAll(Jedis.java:863)

jedis并不是线程安全的,于是在程序中改为每个线程只使用一个jedis实例。

较好的解决办法是使用JedisPool,见官方文档:https://github.com/xetorthio/jedis/wiki/Getting-started

先初始化一个池,可以设置一些参数,如setMaxActive,setMaxIdle等:

JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");



然后就可以从池中取出一个实例:
  

 Jedis jedis = pool.getResource();
    try {
      /// ... do stuff here ... for example
      jedis.set("foo", "bar");
      String foobar = jedis.get("foo");
      jedis.zadd("sose", 0, "car"); jedis.zadd("sose", 0, "bike");
      Set<String> sose = jedis.zrange("sose", 0, -1);
    } finally {
      /// ... it's important to return the Jedis instance to the pool once you've finished using it
      pool.returnResource(jedis);
    }
    /// ... when closing your application:
    pool.destroy();

用完要记得放回池,不用了需要销毁。



http://blog.sina.com.cn/s/blog_6acdaf6d0101509e.html

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

java redis client的链接问题,报标题中出现的错误主要原因是初始化了一个redispool,没有执行释放操作,有可能你调用释放的操作,但是你在执行释放执行进行了条件判断,直接return,没有执行到释放的操作,我们遇到的就是这种情况。

调用jedis client的JedisPool.java

定义一个java的RedisClient

public class RedisClient {
  private static JedisPool
pool;
  private static String
host = "127.0.0.1";
  private static int port
= 6379;
  private static int
timeout = 60 * 1000;
  private static int
maxActive = 100;
  private static int
maxIdle = 20;
  private static long
maxWait = 1000;
  public static final int
EXPIRE_TIME = 86400;
  private static
org.slf4j.Logger logger_ = org.slf4j.LoggerFactory
      .getLogger(RedisClient.class.getName());
  public static void
initPool() {
    logger_.info("Init Redis Pool [{}]:[{}]", host,
port);
    JedisPoolConfig config = new
JedisPoolConfig();
    config.setMaxActive(maxActive);
    config.setMaxIdle(maxIdle);
    config.setMaxWait(maxWait);
    config.setTestOnBorrow(false);
    pool = new JedisPool(config, host, port,
timeout);// 线程数量限制,IP地址,端口,超时时间
  }
  public static Jedis
getJedis() {
    if (pool == null)
      initPool();
    return pool.getResource();
  }
   
   public
static void returnJedis(Jedis jedis) {
    if (jedis != null)
      pool.returnResource(jedis);
  }
}
  
------------------------------------------------------------------------------------
Jedis jedis = RedisClient.getJedis();
RedisClient.returnJedis()

 redis client连接超时

在用jedis客户端对redis进行压力测试时,经常会出现下述错误:

Exception in thread "Thread-565" redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
        at redis.clients.jedis.Protocol.process(Protocol.java:79)
        at redis.clients.jedis.Protocol.read(Protocol.java:131)
        at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:162)
        at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:76)
        at redis.clients.jedis.Connection.sendCommand(Connection.java:79)
        at redis.clients.jedis.BinaryClient.select(BinaryClient.java:148)
        at redis.clients.jedis.Jedis.select(Jedis.java:328)
        at RedisThread.run(RedisThread.java:15)
        at java.lang.Thread.run(Thread.java:679)
Caused by: java.net.SocketTimeoutException: Read timed out
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.read(SocketInputStream.java:146)
        at java.net.SocketInputStream.read(SocketInputStream.java:107)
        at redis.clients.util.RedisInputStream.fill(RedisInputStream.java:109)
        at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:45)
        at redis.clients.jedis.Protocol.process(Protocol.java:64)
        ... 8 more
从中可以看出,出错的原因是线程等待超时,断开连接,所以可以通过手动设置超时时间来避免这个错误。查询Jedis构造函数,可以发现其中一个构造函数如下,可以在其中指出客户端等待的超时时间:
public Jedis(final String host, final int port, final int timeout) {
super(host, port, timeout);
}


Jedis对象创建时,在构造函数中按照实际需求设置timeout的大小可以避免上述错误的出现。


© 著作权归作者所有

-奋斗小青年-
粉丝 1
博文 3
码字总数 1383
作品 0
程序员
私信 提问
Spring Boot学习笔记

多模块开发 [SpringBoot学习]-IDEA创建Gradle多Module结构的SpringBoot项目 RabbitMQ RabbitMQ 安装 linux安装RabbitMQ详细教程 Ubuntu 16.04 RabbitMq 安装与运行(安装篇) ubantu安装...

OSC_fly
2018/07/26
0
0
redis(三)与spring整合

一、 JAVA操作redis通常使用的是Jedis,通过java代码来操作redis的数据存储读取等操作,用过的人应该知道,Jedis客户端已经足够简单和轻量级了,但是呢,在此同时,Spring也为Redis提供了支持...

废柴
2018/07/11
0
0
dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(六)Spring中Redis的缓存的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010046908/article/details/54174622 前面已经写了四篇关于dubbo2.5-spring4-mybastis3.2-springmvc4-mongo...

请叫我东子
01/05
0
0
Spring整合redis(设置密码)完整版

博主在上个项目中使用了redis,开始使用的jedisPool连接池的方式进行整合,发现这样是不安全,调研了一下,选择了设置redis密码重新整合,总结经验如下: 1)导入Spring-redis的jar具体如下:...

小伟_乌牛
2017/10/30
0
0
Spring实践--spring cache 与redis缓存整合

【Spring】17、spring cache 与redis缓存整合 spring cache,基本能够满足一般应用对缓存的需求,但现实总是很复杂,当你的用户量上去或者性能跟不上,总需要进行扩展,这个时候你或许对其提...

spinachgit
2017/12/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java 静态代理、Java动态代理、CGLIB动态代理

Java 的代理就是客户类不再直接和委托类打交道, 而是通过一个中间层来访问, 这个中间层就是代理。为啥要这样呢, 是因为使用代理有 2 个优势: 可以隐藏委托类的实现 可以实现客户与委托类之间...

gaomq
15分钟前
0
0
win10部署sonar代码扫描工具

一 安装MySQL解压版 此部分参看Win10安装MySQL5.7.22 解压缩版(手动配置)方法 1、下载 mysql-5.7.26-winx64.zip 解压之后生成 mysql-5.7.26-winx64 文件夹。 2、在D盘创建Mysql目录 D:\MyS...

BG2KNT
17分钟前
0
0
小程序的rpx以及rem和px的换算

(1).rpx:不论哪个型号的手机,屏幕宽度都是750rpx rpx与px的转换,根据设计稿换算 例如:设计稿750px宽度,ps上量出或者标出的宽度是多少,那么就定义多少rpx,也就是,1px = 1rpx 例如:设计...

流年那么伤
17分钟前
0
0
当我说要做大数据工程师时他们都笑我,直到三个月后……

申明: 本文旨在为普通程序员(Java程序员最佳)提供一个入门级别的大数据技术学习路径,不适用于大数据工程师的进阶学习,也不适用于零编程基础的同学。 前言: 一、背景介绍 二、大数据介绍...

求神
22分钟前
0
0
python3 案例分享--天气预报

通过输入城市就能查出最近几日的天气情况, 代码如下: from tkinter import *import urllib.requestimport gzipimport jsonfrom tkinter import messageboxroot = Tk()...

lyle_luo
30分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部