在springmvc中配置jedis:

主要学习https://github.com/thinkgem/jeesite。一下代码均参考于此并稍作修改。

1.jedis

首先,需要添加jedis:

<!--jedis-->
<dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.8.0</version>
</dependency>

2.applicationContext-jedis.xml

然后,springmvc完成基本配置。添加jedispool的bean即可。在spring容器中添加applicationContext-jedis.xml:

在applicationContext-jedis.xml中添加:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       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">
    <!-- 加载配置属性文件 -->
    <context:property-placeholder ignore-unresolvable="true" location="classpath:db.properties" />

    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="300"/> <!--最大能够保持idel状态的对象数-->
        <property name="maxTotal" value="60000"/><!--最大分配的对象数-->
        <property name="testOnBorrow" value="true"/><!--当调用borrow Oject方法时,是否进行有效性检查-->
    </bean>

    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg index="0" ref="jedisPoolConfig"/>
        <constructor-arg index="1" value="${redis.host}"/>
        <constructor-arg index="2" value="${redis.port}" type="int"/>
        <constructor-arg index="3" value="${redis.timeout}" type="int"/>
        <constructor-arg index="4" value="${redis.auth}"/>
    </bean>
</beans>

注解:参考的源码中的jedisPool配置只有三个参数:config,host,port。我复制后的结果总是getResource失败,因为我的redis添加了auth,所以猜测是不是没通过auth的原因。于是打开JedisPool的源码:

  1 package redis.clients.jedis;
  2 
  3 import java.net.URI;
  4 
  5 import org.apache.commons.pool2.impl.GenericObjectPool;
  6 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
  7 
  8 import redis.clients.jedis.exceptions.JedisException;
  9 import redis.clients.util.JedisURIHelper;
 10 import redis.clients.util.Pool;
 11 
 12 public class JedisPool extends Pool<Jedis> {
 13 
 14   public JedisPool() {
 15     this(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT);
 16   }
 17 
 18   public JedisPool(final GenericObjectPoolConfig poolConfig, final String host) {
 19     this(poolConfig, host, Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, null,
 20         Protocol.DEFAULT_DATABASE, null);
 21   }
 22 
 23   public JedisPool(String host, int port) {
 24     this(new GenericObjectPoolConfig(), host, port, Protocol.DEFAULT_TIMEOUT, null,
 25         Protocol.DEFAULT_DATABASE, null);
 26   }
 27 
 28   public JedisPool(final String host) {
 29     URI uri = URI.create(host);
 30     if (JedisURIHelper.isValid(uri)) {
 31       String h = uri.getHost();
 32       int port = uri.getPort();
 33       String password = JedisURIHelper.getPassword(uri);
 34       int database = JedisURIHelper.getDBIndex(uri);
 35       this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(h, port,
 36           Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, password, database, null),
 37           new GenericObjectPoolConfig());
 38     } else {
 39       this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(host,
 40           Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null,
 41           Protocol.DEFAULT_DATABASE, null), new GenericObjectPoolConfig());
 42     }
 43   }
 44 
 45   public JedisPool(final URI uri) {
 46     this(new GenericObjectPoolConfig(), uri, Protocol.DEFAULT_TIMEOUT);
 47   }
 48 
 49   public JedisPool(final URI uri, final int timeout) {
 50     this(new GenericObjectPoolConfig(), uri, timeout);
 51   }
 52 
 53   public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,
 54       int timeout, final String password) {
 55     this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, null);
 56   }
 57 
 58   public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port) {
 59     this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE, null);
 60   }
 61 
 62   public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port,
 63       final int timeout) {
 64     this(poolConfig, host, port, timeout, null, Protocol.DEFAULT_DATABASE, null);
 65   }
 66 
 67   public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,
 68       int timeout, final String password, final int database) {
 69     this(poolConfig, host, port, timeout, password, database, null);
 70   }
 71 
 72   public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,
 73       int timeout, final String password, final int database, final String clientName) {
 74     this(poolConfig, host, port, timeout, timeout, password, database, clientName);
 75   }
 76 
 77   public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,
 78       final int connectionTimeout, final int soTimeout, final String password, final int database,
 79       final String clientName) {
 80     super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password,
 81         database, clientName));
 82   }
 83 
 84   public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri) {
 85     this(poolConfig, uri, Protocol.DEFAULT_TIMEOUT);
 86   }
 87 
 88   public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, final int timeout) {
 89     this(poolConfig, uri, timeout, timeout);
 90   }
 91 
 92   public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri,
 93       final int connectionTimeout, final int soTimeout) {
 94     super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, null));
 95   }
 96 
 97   @Override
 98   public Jedis getResource() {
 99     Jedis jedis = super.getResource();
100     jedis.setDataSource(this);
101     return jedis;
102   }
103 
104   /**
105    * @deprecated starting from Jedis 3.0 this method will not be exposed.
106    * Resource cleanup should be done using @see {@link redis.clients.jedis.Jedis#close()}
107    */
108   @Override
109   @Deprecated
110   public void returnBrokenResource(final Jedis resource) {
111     if (resource != null) {
112       returnBrokenResourceObject(resource);
113     }
114   }
115 
116   /**
117    * @deprecated starting from Jedis 3.0 this method will not be exposed.
118    * Resource cleanup should be done using @see {@link redis.clients.jedis.Jedis#close()}
119    */
120   @Override
121   @Deprecated
122   public void returnResource(final Jedis resource) {
123     if (resource != null) {
124       try {
125         resource.resetState();
126         returnResourceObject(resource);
127       } catch (Exception e) {
128         returnBrokenResource(resource);
129         throw new JedisException("Could not return the resource to the pool", e);
130       }
131     }
132   }
133 }

看到有password的参数配置,如果没有配置的话默认为null。到这一步我便没有往下深入看了,因为我连接的redis中有auth,原谅我的不求甚解。于是,我接着配置timeout和auth。timeout直接还是源码的默认值。后面的代码测试通过。在这里我了解到spring的bean注入的几个参数含义:比如property表示属性注入,constructor表示构造函数的参数注入。

为了更清楚的表达,redis要设置db,配置文件参数也做一下改动:

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="300" /> <!-- 最大能够保持idel状态的对象数  -->
        <property name="maxTotal" value="60000" /> <!-- 最大分配的对象数 -->
        <property name="testOnBorrow" value="true" /> <!-- 当调用borrow Object方法时,是否进行有效性检查 -->
    </bean>
    
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="${redis.host}" />
        <constructor-arg name="port" value="${redis.port}" type="int" />
        <constructor-arg name="timeout" value="${redis.timeout}" type="int" />
        <constructor-arg name="password" value="#{'${redis.password}'!=''?'${redis.password}':null}" />
        <constructor-arg name="database" value="${redis.db.index}" type="int" />
    </bean>

最后一项参数是选择redis的db,我认为通常默认连接的都是redis的0,那么我们的开发环境为了不冲突,应该另外设置。但JedisPool并没有只有指定db的构造函数,所以选择了这个构造函数。唯一的问题是,默认我们的redis是没有密码的,那么这里也填null而不是空字符串哦。所以,这里使用spring spEL表达式来填充空。对应的配置文件如下:

#redis settings
redis.keyPrefix=wz
redis.host=127.0.0.1
redis.port=6379
redis.timeout=2000
#注意,如果没有password,此处不设置值,但这一项要保留
redis.password=
redis.db.index=1

3.  JedisUtil

 3.1 getResource

上面设置好了JedisPool,这里就要获取jedis。然后就可以利用jedis进行操作了。

 1  /**
 2      * 获取资源
 3      * @return
 4      */
 5     public static Jedis getResource() {
 6         Jedis jedis = null;
 7         try {
 8             jedis = jedisPool.getResource();
 9             logger.debug("getResource:{}",jedis);
10         } catch (Exception e) {
11             logger.error("getResource:{}",e);
12             if (jedis!=null)
13             jedis.close();
14             throw  e;
15         }
16         return jedis;
17     }

但是,为了更加自定义的设置db,这里也可以加一个db的选择:

    public static Jedis getResource() throws JedisException {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.select(Integer.parseInt(DB_INDEX));
//            logger.debug("getResource.", jedis);
        } catch (JedisException e) {
            logger.warn("getResource.", e);
            returnBrokenResource(jedis);
            throw e;
        }
        return jedis;
    }

3.1.1设置prefix

为了我们的key与其他app不冲突,我们最后为我们key统一增加一个标识,这种做法类似选择一个表。

private static String setPrefix(String key) {
    key=KEY_PREFIX+"_"+key;
    return key;
}

在任何使用到redis的地方,配置key的prefix。比如get 和 set:

    public static String get(String key) {
        key = setPrefix(key);
        String value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                value = jedis.get(key);
                value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
                logger.debug("get {} = {}", key, value);
            }
        } catch (Exception e) {
            logger.warn("get {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }
    public static String set(String key, String value, int cacheSeconds) {
        key = setPrefix(key);
        String result = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.set(key, value);
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            logger.debug("set {} = {}", key, value);
        } catch (Exception e) {
            logger.warn("set {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

3.2 Object对象的缓存

通过使用jedis基本可以完成任何操作了。这里添加一个缓存对象的功能。java对象的缓存利用序列化实现,因此,需要缓存的对象必须实现了serializable接口。关于如何序列化,参考:将对象序列化和反序列化

 1   /**
 2      * 设置缓存
 3      * @param key String
 4      * @param value Object对象
 5      * @param cacheSeconds 超时时间,0为不超时
 6      * @return
 7      */
 8     public static String setObject(String key,Object value,int cacheSeconds){
 9         String result = null;
10         Jedis jedis = null;
11         try {
12             jedis = getResource();
13             result = jedis.set(getBytesKey(key),toBytes(value));
14             if (cacheSeconds!=0){
15                 jedis.expire(key,cacheSeconds);
16             }
17             logger.debug("setObject {}={}",key,value);
18         } catch (Exception e) {
19             logger.warn("setObject {}  失败:{}",key,e);
20         } finally {
21             jedis.close();
22         }
23         return result;
24     }
25 /**
26      * 获取缓存
27      * @param key
28      * @return 对象(反序列化)
29      */
30     public static Object getObject(String key){
31         Object value = null;
32         Jedis jedis = null;
33         try {
34             jedis = getResource();
35             byte[] bytes = jedis.get(getBytesKey(key));
36             value =  toObject(bytes);
37             logger.debug("getObject {}={}",key,value);
38         } catch (Exception e) {
39             logger.warn("getObject {}错误:{}",key,e.getMessage());
40             e.printStackTrace();
41         } finally {
42             jedis.close();
43         }
44         return value;
45     }
46  /**
47      * 将key转换为byte[]
48      * @param object
49      * @return
50      */
51     private static byte[] getBytesKey(Object object) {
52         if(object instanceof String){
53             return StringUtils.getBytes((String) object);
54         }else {
55             return ObjectUtils.serialize(object);
56         }
57     }
58 
59     /**
60      * Object转换为byte[]类型
61      * @param value Object对象
62      * @return byte[]数组
63      */
64     private static byte[] toBytes(Object value) {
65         return ObjectUtils.serialize(value);
66     }
67 
68     /**
69      * byte[]转换为object
70      * @param bytes
71      * @return
72      */
73     private static Object toObject(byte[] bytes) {
74         return ObjectUtils.unserialize(bytes);
75     }

3.3 ObjectList对象缓存

我们平时用到的list基本都是ObjectList,即list的元素为object而不是String。这样就需要特定方法来缓存了。

采用同样的方式,将object序列化为字节数组,然后存储起来。取出的时候再反序列化,因此object必须实现了serializable接口,而且static的成员不能序列化或者说序列化的结果为默认值。原因参考:将对象序列化和反序列化

  1 /**
  2      * 获取list缓存
  3      * @param key
  4      * @return
  5      */
  6     public static List<String> getList(String key){
  7         key = addDatabaseName(key);
  8         List<String> value = null;
  9         Jedis jedis = null;
 10         try {
 11             jedis = getResource();
 12             value = jedis.lrange(key, 0, -1);
 13             logger.debug("getList {}={}",key,value);
 14         } catch (Exception e) {
 15             logger.warn("getList {}失败:{}",key,e);
 16             e.printStackTrace();
 17         } finally {
 18             jedis.close();
 19         }
 20         return value;
 21     }
 22 
 23     /**
 24      * 获取list缓存,元素是object
 25      * @param key
 26      * @return
 27      */
 28     public static List<Object> getObjectList(String key){
 29         key = addDatabaseName(key);
 30         List<Object> value = null;
 31         Jedis jedis = null;
 32         try {
 33             jedis = getResource();
 34             List<byte[]> list = jedis.lrange(getBytesKey(key), 0, -1);
 35             value = Lists.newArrayList();
 36             for (byte[] bytes : list) {
 37                 value.add(toObject(bytes));
 38             }
 39             logger.debug("getObjectList {}={}",key,value);
 40         }catch (Exception e){
 41             logger.warn("getObjectList {} 失败:{}",key,e);
 42             e.printStackTrace();
 43         }finally {
 44             jedis.close();
 45         }
 46         return value;
 47     }
 48 
 49     /**
 50      * 设置list缓存
 51      * @param key
 52      * @param value
 53      * @param cacheSeconds
 54      * @return
 55      */
 56     public static long setList(String key,List<String> value,int cacheSeconds){
 57         key = addDatabaseName(key);
 58         long result = 0;
 59         Jedis jedis = null;
 60         try {
 61             jedis = getResource();
 62             jedis.del(key);
 63             String[] arr = new String[value.size()];
 64             value.toArray(arr);
 65             result = jedis.rpush(key,arr);
 66             if (cacheSeconds!=0){
 67                 jedis.expire(key,cacheSeconds);
 68             }
 69             logger.debug("setList {}={}",key,value);
 70         }catch (Exception e){
 71             logger.warn("setList {} 错误:",key,e);
 72             e.printStackTrace();
 73         }finally {
 74             jedis.close();
 75         }
 76         return result;
 77     }
 78 
 79     /**
 80      * 设置list缓存,list的元素为object
 81      * @param key
 82      * @param value
 83      * @param cacheSeconds
 84      * @return
 85      */
 86     public static long setObjectList(String key,List<Object> value ,int cacheSeconds){
 87         key = addDatabaseName(key);
 88         long result = 0;
 89         Jedis jedis = null;
 90         try {
 91             jedis = getResource();
 92             jedis.del(key);
 93             ArrayList<byte[]> list = Lists.newArrayList();
 94             for (Object o : value) {
 95                 list.add(toBytes(o));
 96             }
 97             byte[] []arr = new byte[list.size()][];
 98             list.toArray(arr);
 99             result = jedis.rpush(getBytesKey(key),arr);
100             if(cacheSeconds!=0){
101                 jedis.expire(key,cacheSeconds);
102             }
103             logger.debug("setObjectList {}={}",key,value);
104         }catch (Exception e){
105             logger.warn("setObjectList {} 错误:{}",key,e);
106             e.printStackTrace();
107         }
108         return result;
109     }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一个爱瞎折腾的程序猿

sqlserver使用存储过程跟踪SQL

USE [master] GO /****** Object: StoredProcedure [dbo].[sp_perfworkload_trace_s...

2110
来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

32210
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4055
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2617
来自专栏芋道源码1024

熔断器 Hystrix 源码解析 —— 断路器 HystrixCircuitBreaker

本文主要基于 Hystrix 1.5.X 版本 1. 概述 2. HystrixCircuitBreaker 3. HystrixCircuitBreaker....

5377
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.2K7
来自专栏落花落雨不落叶

canvas画简单电路图

64411
来自专栏张善友的专栏

Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR

Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverligh...

2717
来自专栏魂祭心

原 canvas绘制clock

4204
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4878

扫码关注云+社区