zoukankan      html  css  js  c++  java
  • 在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 }
    View Code

    看到有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     }
    View Code
  • 相关阅读:
    程序员新年要实现的10个愿望
    编写超级可读代码的15个最佳实践
    LeetCode 最大子序和
    LeetCode 最大正方形
    LeetCode 买卖股票的最佳时机 II
    LeetCode 买卖股票的最佳时机
    B树和B+树
    SQL的几种连接
    LeetCode 无重复字符的最长子串
    LeetCode 翻转字符串里的单词
  • 原文地址:https://www.cnblogs.com/woshimrf/p/5211253.html
Copyright © 2011-2022 走看看