Java Spring mvc 操作 Redis 及 Redis 集群

关于 Redis 集群搭建可以参考我的另一篇文章 Redis集群搭建与简单使用

Redis 是什么,能做什么

Redis 是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串哈希表列表集合有序集合位图hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel 提供高可用,通过 Redis Cluster 提供自动分区。(摘自Redis 官网)

作为内存数据库,在现代互联网 web 系统中,还是主要将 Redis 作为缓存使用。大型互联网 Web 系统对性能要求很高,而在前端和数据层之间增加数据缓存已成为必不可少的手段之一,当前比较流行的两个技术就是 Redis 和 Memcached,至于两者有什么区别,不是本文要说的内容。本文主要讲 Java Web 如何操作 Redis 及 Redis 集群。

一般 Java 程序操作Redis

Redis 提供了多种语言的客户端,在 Java 中最流行的是 Jedis 。访问可查看源码及使用方式。目前 Jedis 最新版本是2.9.0。无论是单机还是集群,Jedis 都有很详细的说明和实例代码,这里只做简单说明。如果用 Maven 做包管理,需要引用  jedis 包,本例使用最新的2.9.0版本,如下:

1
2
3
4
5
< dependency >
       < groupId >redis.clients</ groupId >
       < artifactId >jedis</ artifactId >
       < version >2.9.0</ version >
</ dependency >  

操作 Redis 单机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import  redis.clients.jedis.Jedis;
import  redis.clients.jedis.JedisPool;
import  redis.clients.jedis.JedisPoolConfig;
 
/**
  * Created by fengdezitai on 2016/10/9.
  */
public  class  JedisClient {
 
     private  static  final  String host=  "192.168.31.121" ;
 
     private  static  final  JedisClient jedisClient =  new  JedisClient();
 
     private  Jedis jedis =  null ;
     /**
      * 私有构造函数
      */
     private  JedisClient(){}
 
     public  static  JedisClient getInstance(){
         return  jedisClient;
     }
 
     private  JedisPoolConfig getPoolConfig(){
         JedisPoolConfig jedisPoolConfig =  new  JedisPoolConfig();
         jedisPoolConfig.setMaxIdle( 10 );
         jedisPoolConfig.setMaxTotal( 100 );
         jedisPoolConfig.setMaxWaitMillis( 3000 );
         return  jedisPoolConfig;
     }
 
     /**
      * 添加
      * @param key
      * @param value
      * @return
      * @throws Exception
      */
     public  Boolean add(String key,String value)  throws  Exception{
         JedisPool pool =  new  JedisPool(getPoolConfig(),host);
         Jedis jedis =  null ;
         try  {
             jedis = pool.getResource();
             if (jedis.exists(key)){
                 throw  new  Exception(String.format( "key (%s) 已存在 " ,key));
             }
             jedis.set(key,value);
 
         } catch  (Exception e){
             throw  e;
         }
         finally  {
             if (jedis!= null ){
                 jedis.close();
             }
         }
         pool.destroy();
         return  true ;
     }
 
     /**
      * 获取值
      * @param key
      * @return
      * @throws Exception
      */
     public  String get(String key)  throws  Exception{
         JedisPool pool =  new  JedisPool(getPoolConfig(),host);
         Jedis jedis =  null ;
         String result =  "" ;
         try  {
             jedis = pool.getResource();
             result = jedis.get(key);
         } catch  (Exception e){
             throw  e;
         }
         finally  {
             if (jedis!= null ){
                 jedis.close();
             }
         }
         pool.destroy();
         return  result;
     }
 
     public  static  void  main(String[] args) {
         JedisClient jedisClient = JedisClient.getInstance();
         try  {
             /*Boolean result = jedisClient.add("hello", "redis1");
             if(result){
                 System.out.println("success");
             }*/
 
             System.out.println(jedisClient.get( "hello" ));
         } catch  (Exception e){
             e.printStackTrace();
         }
     }
}

操作 redis 集群

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import  redis.clients.jedis.*;
import  java.util.HashSet;
import  java.util.Set;
 
/**
  * Created by fengdezitai on 2016/10/13.
  */
public  class  JedisClusterClient {
 
     private  static  int  count =  0 ;
 
     private  static  final  JedisClusterClient redisClusterClient =  new  JedisClusterClient();
 
     /**
      * 私有构造函数
      */
     private  JedisClusterClient() {}
 
     public  static  JedisClusterClient getInstance() {
         return  redisClusterClient;
     }
 
     private  JedisPoolConfig getPoolConfig(){
         JedisPoolConfig config =  new  JedisPoolConfig();
         config.setMaxTotal( 1000 );
         config.setMaxIdle( 100 );
         config.setTestOnBorrow( true );
         return  config;
     }
 
     public  void  SaveRedisCluster() {
         Set<HostAndPort> jedisClusterNodes =  new  HashSet<HostAndPort>();
         jedisClusterNodes.add( new  HostAndPort( "192.168.31.245" 7000 ));
         jedisClusterNodes.add( new  HostAndPort( "192.168.31.245" 7001 ));
         jedisClusterNodes.add( new  HostAndPort( "192.168.31.245" 7002 ));
         jedisClusterNodes.add( new  HostAndPort( "192.168.31.210" 7003 ));
         jedisClusterNodes.add( new  HostAndPort( "192.168.31.210" 7004 ));
         jedisClusterNodes.add( new  HostAndPort( "192.168.31.210" 7005 ));
 
         JedisCluster jc =  new  JedisCluster(jedisClusterNodes,getPoolConfig());
         jc.set( "cluster" "this is a redis cluster" );
         String result = jc.get( "cluster" );
         System.out.println(result);
     }
 
     public  static  void  main(String[] args) {
         JedisClusterClient jedisClusterClient = JedisClusterClient.getInstance();
         jedisClusterClient.SaveRedisCluster();
     }
}  

spring mvc 操作 Redis

在 Spring mvc 中操作 Redis ,首先当然要搭好 Spring mvc 框架了。以下是在假设 Spring mvc 环境已经架好的情况下。本例中 Spring 版本为 4.3.2 RELEASE。关于 Spring 的 maven 引用如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<!-- spring版本号 -->
<spring.version>4.3.2.RELEASE< /spring .version>
 
<!-- spring核心包 -->
     <!-- springframe start -->
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring-core< /artifactId >
       <version>${spring.version}< /version >
       <exclusions>
         <exclusion>
           <groupId>commons-logging< /groupId >
           <artifactId>commons-logging< /artifactId >
         < /exclusion >
       < /exclusions >
     < /dependency >
 
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring-web< /artifactId >
       <version>${spring.version}< /version >
     < /dependency >
 
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring-oxm< /artifactId >
       <version>${spring.version}< /version >
     < /dependency >
 
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring-tx< /artifactId >
       <version>${spring.version}< /version >
     < /dependency >
 
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring-jdbc< /artifactId >
       <version>${spring.version}< /version >
     < /dependency >
 
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring-webmvc< /artifactId >
       <version>${spring.version}< /version >
       <exclusions>
         <exclusion>
           <groupId>commons-logging< /groupId >
           <artifactId>commons-logging< /artifactId >
         < /exclusion >
       < /exclusions >
     < /dependency >
 
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring-aop< /artifactId >
       <version>${spring.version}< /version >
     < /dependency >
 
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring-context-support< /artifactId >
       <version>${spring.version}< /version >
     < /dependency >
 
 
     <dependency>
       <groupId>org.springframework< /groupId >
       <artifactId>spring- test < /artifactId >
       <version>${spring.version}< /version >
     < /dependency >
     <!-- springframe end -->

操作 Redis 单机

只用 Jedis 自己实现注入(区别于下面的引用spring-data-redis) 

把前面的 JedisClient 代码拿过来引用即可,只需实现一个访问 Redis 的 Service ,就可以集成到 Spring mvc 。Service 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import  org.springframework.stereotype.Service;
import  util.JedisClient;
 
/**
  * Created by fengdezitai on 2016/10/9.
  */
@Service
public  class  RedisService {
 
     public  String get(String key)  throws  Exception{
         JedisClient jedisClient = JedisClient.getInstance();  //上面实现的JedisClient
         String result =  "" ;
         try  {
             result = jedisClient.get( "hello" );
         } catch  (Exception e){
             throw  e;
         }
         return  result;
     }
}

Controller 实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Controller
@RequestMapping (value =  "redisAllInOne" )
public  class  RedisAllInOneController {
 
     @Autowired
     private  RedisService redisService;
 
     @RequestMapping (value =  "get" ,method = RequestMethod.GET)
     @ResponseBody
     public  Object getByMyService(String key){
         try  {
             String result = redisService.get(key);
             return  result;
         } catch  (Exception e){
             e.printStackTrace();
         }
         return  null ;
     }
}  

用 spring-data-redis 包做集成

上面是自己实现的注入,这里用 spring-data-redis 进行集成,只需简单配置即可,需要引用 maven 包如下,版本为目前最新版 1.7.2.RELEASE:

1
2
3
4
5
<dependency>
       <groupId>org.springframework.data< /groupId >
       <artifactId>spring-data-redis< /artifactId >
       <version>1.7.2.RELEASE< /version >
     < /dependency >

使用 spring-data-redis ,即省去了自己实现注入的过程,通过它提供的一些配置,即可实现连接池配置、RedisTemplate 配置、JedisConnectionFactory 配置;通过 JedisConnectionFactory 可配置连接池参数、redis 服务器、端口、密码、超时时间、database索引等;RedisTemplate 即注入的bean ,可以使用 RedisTemplate 自动注入的实体进行 redis 的一系列操作,具体看配置;

redis 服务属性配置文件:

1
2
3
4
5
6
7
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow= true
redis.host=192.168.31.121
redis.port=6379
redis.password=password
redis.timeout=3000

spring-data-redis xml 配置文件 redis-context.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!-- jedis 连接池 配置 -->
     <bean  id = "poolConfig"  class= "redis.clients.jedis.JedisPoolConfig"  >
         <property name= "maxIdle"  value= "${redis.maxIdle}"  />
         <property name= "maxWaitMillis"  value= "${redis.maxWait}"  />
         <property name= "testOnBorrow"  value= "${redis.testOnBorrow}"  />
     < /bean >
     <!-- redis服务器中心 -->
     <bean  id = "connectionFactory"  class= "org.springframework.data.redis.connection.jedis.JedisConnectionFactory"  >
         <property name= "poolConfig"  ref= "poolConfig"  />
         <property name= "port"  value= "${redis.port}"  />
         <property name= "hostName"  value= "${redis.host}"  />
         <!--<property name= "password"  value= "${redis.password}"  />-->
         <property name= "timeout"  value= "${redis.timeout}"  >< /property >
         <property name= "database"  value= "1" >< /property >
     < /bean >
 
     <bean  id = "commonRedisTemplate"  class= "org.springframework.data.redis.core.RedisTemplate"  >
         <property name= "connectionFactory"  ref= "connectionFactory"  />
         <property name= "keySerializer"  ref= "stringRedisSerializer"  />
         <property name= "hashKeySerializer"  ref= "stringRedisSerializer"  />
         <property name= "valueSerializer"  ref= "stringRedisSerializer"  />
         <property name= "hashValueSerializer"  ref= "stringRedisSerializer"  />
     < /bean >
 
     <bean  id = "connectionFactory1"  class= "org.springframework.data.redis.connection.jedis.JedisConnectionFactory"  >
         <property name= "poolConfig"  ref= "poolConfig"  />
         <property name= "port"  value= "${redis.port}"  />
         <property name= "hostName"  value= "${redis.host}"  />
         <!--<property name= "password"  value= "${redis.password}"  />-->
         <property name= "timeout"  value= "${redis.timeout}"  >< /property >
         <property name= "database"  value= "2" >< /property >
     < /bean >
 
     <bean  id = "stringRedisSerializer" class= "org.springframework.data.redis.serializer.StringRedisSerializer"  />
     <bean  id = "cacheRedisTemplate"  class= "org.springframework.data.redis.core.RedisTemplate"  >
         <property name= "connectionFactory"  ref= "connectionFactory1"  />
         <property name= "keySerializer"  ref= "stringRedisSerializer"  />
         <property name= "hashKeySerializer"  ref= "stringRedisSerializer"  />
         <property name= "valueSerializer"  ref= "stringRedisSerializer"  />
         <property name= "hashValueSerializer"  ref= "stringRedisSerializer"  />
     < /bean >

之后在 spring 配置文件中引用以上文件:

1
< import  resource= "redis-context.xml"  />  

解释一下上面的配置:

poolConfig 即配置 redis 连接池,之后配置了两个 JedisConnectionFactory 和 RedisTemplate ,一个 RedisTemplate 对应一个 JedisConnectionFactory ,这样可以配置根据场景配置不同的 Redis 连接,比如超时时间要求不一致、database 0-15 可以存储不同的数据等。这里就配置了database 1 和 2 ,调用 commonRedisTemplate 会存到 database1 ,调用 cacheRedisTemplate 会存到 database2。

之后在 Service 层即可注入并引用这两个 RedisTemplate ,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import  org.apache.commons.lang3.StringUtils;
import  org.springframework.dao.DataAccessException;
import  org.springframework.data.redis.connection.RedisConnection;
import  org.springframework.data.redis.core.RedisCallback;
import  org.springframework.data.redis.core.RedisTemplate;
import  org.springframework.stereotype.Repository;
 
import  javax.annotation.Resource;
import  java.io.*;
 
@Repository
public  class  RedisCache {<br>  
     @Resource (name =  "cacheRedisTemplate" )
     private  RedisTemplate<String, String> cacheRedisTemplate;
 
     public  void  put(Object key, Object value) {
         if ( null  == value) {
             return ;
         }
 
         if (value  instanceof  String) {
             if (StringUtils.isEmpty(value.toString())) {
                 return ;
             }
         }
 
         // TODO Auto-generated method stub
         final  String keyf = key +  "" ;
         final  Object valuef = value;
         final  long  liveTime =  86400 ;
 
         cacheRedisTemplate.execute( new  RedisCallback<Long>() {
             public  Long doInRedis(RedisConnection connection)
                     throws  DataAccessException {
                 byte [] keyb = keyf.getBytes();
                 byte [] valueb = toByteArray(valuef);
                 connection.set(keyb, valueb);
                 if  (liveTime >  0 ) {
                     connection.expire(keyb, liveTime);
                 }
                 return  1L;
             }
         });
     }
 
     public  Object get(Object key) {
         final  String keyf = (String) key;
         Object object;
         object = cacheRedisTemplate.execute( new  RedisCallback<Object>() {
             public  Object doInRedis(RedisConnection connection)
                     throws  DataAccessException {
 
                 byte [] key = keyf.getBytes();
                 byte [] value = connection.get(key);
                 if  (value ==  null ) {
                     return  null ;
                 }
                 return  toObject(value);
 
             }
         });
 
         return  object;
     }
 
     /**
      * 描述 : <byte[]转Object>. <br>
      * <p>
      * <使用方法说明>
      * </p>
      *
      * @param bytes
      * @return
      */
     private  Object toObject( byte [] bytes) {
         Object obj =  null ;
         try  {
             ByteArrayInputStream bis =  new  ByteArrayInputStream(bytes);
             ObjectInputStream ois =  new  ObjectInputStream(bis);
             obj = ois.readObject();
             ois.close();
             bis.close();
         catch  (IOException ex) {
             ex.printStackTrace();
         catch  (ClassNotFoundException ex) {
             ex.printStackTrace();
         }
         return  obj;
     }
 
     private  byte [] toByteArray(Object obj) {
         byte [] bytes =  null ;
         ByteArrayOutputStream bos =  new  ByteArrayOutputStream();
         try  {
             ObjectOutputStream oos =  new  ObjectOutputStream(bos);
             oos.writeObject(obj);
             oos.flush();
             bytes = bos.toByteArray();
             oos.close();
             bos.close();
         catch  (IOException ex) {
             ex.printStackTrace();
         }
         return  bytes;
     }
}

最后在 Controller 中调用即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Autowired
private  RedisCache redisCache;
 
 
@RequestMapping (value =  "get" , method = RequestMethod.GET)
@ResponseBody
public  Object getByMyService(String key) {
     try  {
         String result = redisService.get(key);
         return  result;
     catch  (Exception e) {
         e.printStackTrace();
     }
     return  null ;
}
 
@RequestMapping (value =  "save" , method = RequestMethod.GET)
@ResponseBody
public  Object save() {
     Token token =  new  Token();
     token.setAccess_token( "token" );
     token.setExpires_in( 1000 );
     try  {
         redisCache.put( "token" , token);
     catch  (Exception e) {
         e.printStackTrace();
     }
     return  "ok" ;
}  

操作 Redis 集群

只用 Jedis 自己实现注入(区别于下面的引用spring-data-redis)

把前面的 JedisClusterClient 代码拿过来引用即可,只需实现一个访问 Redis 的 Service ,就可以集成到 Spring mvc 。Service 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import  org.springframework.stereotype.Service;
import  util.JedisClusterClient;
 
/**
  * Created by fengdezitai on 2016/10/13.
  */
@Service
public  class  RedisClusterService {
 
     public  void  save()  throws  Exception{
         //调用 JedisClusterClient 中的方法
         JedisClusterClient jedisClusterClient = JedisClusterClient.getInstance();
         try  {
             jedisClusterClient.SaveRedisCluster();
         } catch  (Exception e){
             throw  e;
         }
     }
}

最后在 Controller 中调用实现的 Service 即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Controller
@RequestMapping (value =  "redisCluster" )
public  class  RedisClusterController {
 
     @Autowired
     private  RedisClusterService redisClusterService;
 
     @RequestMapping (value =  "save" ,method = RequestMethod.GET)
     @ResponseBody
     public  Object save(){
         try {
             redisClusterService.save();
         } catch  (Exception e){
             e.printStackTrace();
             return  String.format( "error: %s" ,e.getMessage());
         }
         return  "ok" ;
     }
}  

用 spring-data-redis 包做集成 

Spring 和 spring-data-redis maven 包引用和前面一致,之所以引用 spring-data-redis 1.7.2.RELEASE,是因为目前只有这个最新版本才支持集群操作。

redis 集群服务属性配置

1
2
3
4
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow= false
redis.timeout=3000

spring-data-redis xml 集群配置文件 redis-cluster-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<!-- 连接池 配置 -->
     <bean  id = "poolConfig"  class= "redis.clients.jedis.JedisPoolConfig"  >
         <property name= "maxIdle"  value= "${redis.maxIdle}"  />
         <property name= "maxWaitMillis"  value= "${redis.maxWait}"  />
         <property name= "testOnBorrow"  value= "${redis.testOnBorrow}"  />
     < /bean >
 
 
     <bean  id = "redisClusterConfig" class= "org.springframework.data.redis.connection.RedisClusterConfiguration" >
         <property name= "maxRedirects"  value= "3" >< /property >
         <property name= "clusterNodes" >
             < set >
                 <bean class= "org.springframework.data.redis.connection.RedisNode" >
                     <constructor-arg name= "host"  value= "192.168.31.245" >< /constructor-arg >
                     <constructor-arg name= "port"  value= "7000" >< /constructor-arg >
                 < /bean >
                 <bean class= "org.springframework.data.redis.connection.RedisNode" >
                     <constructor-arg name= "host"  value= "192.168.31.245" >< /constructor-arg >
                     <constructor-arg name= "port"  value= "7001" >< /constructor-arg >
                 < /bean >
                 <bean class= "org.springframework.data.redis.connection.RedisNode" >
                     <constructor-arg name= "host"  value= "192.168.31.245" >< /constructor-arg >
                     <constructor-arg name= "port"  value= "7002" >< /constructor-arg >
                 < /bean >
                  <bean class= "org.springframework.data.redis.connection.RedisNode" >
                     <constructor-arg name= "host"  value= "192.168.31.210" >< /constructor-arg >
                     <constructor-arg name= "port"  value= "7003" >< /constructor-arg >
                 < /bean >
                 <bean class= "org.springframework.data.redis.connection.RedisNode" >
                     <constructor-arg name= "host"  value= "192.168.31.210" >< /constructor-arg >
                     <constructor-arg name= "port"  value= "7004" >< /constructor-arg >
                 < /bean >
                 <bean class= "org.springframework.data.redis.connection.RedisNode" >
                     <constructor-arg name= "host"  value= "192.168.31.210" >< /constructor-arg >
                     <constructor-arg name= "port"  value= "7005" >< /constructor-arg >
                 < /bean >
             < /set >
         < /property >
     < /bean >
 
     <bean  id = "redis4CacheConnectionFactory"
           class= "org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
         <constructor-arg name= "clusterConfig"  ref= "redisClusterConfig"  />
         <property name= "timeout"  value= "${redis.timeout}"  />
         <property name= "poolConfig"  ref= "poolConfig" />
     < /bean >
 
 
     <bean name= "stringRedisSerializer" class= "org.springframework.data.redis.serializer.StringRedisSerializer"  />
     <bean  id = "clusterRedisTemplate"  class= "org.springframework.data.redis.core.RedisTemplate" >
         <property name= "connectionFactory"  ref= "redis4CacheConnectionFactory"  />
         <property name= "keySerializer"  ref= "stringRedisSerializer"  />
         <property name= "hashKeySerializer"  ref= "stringRedisSerializer"  />
         <property name= "valueSerializer"  ref= "stringRedisSerializer"  />
         <property name= "hashValueSerializer"  ref= "stringRedisSerializer"  />
     < /bean >

之后在 Spring 配置文件中引用

1
< import  resource= "redis-cluster-context.xml"  />

解释以上配置

poolConfig是连接池配置,redisClusterConfig 配置了 Redis 集群的各个节点(节点 host 和 port 最好写在属性配置文件中),集群搭建可见 我的 另一篇博客 。然后下面和单机配置一样了,一对 JedisConnectionFactory 和 RedisTemplate 。

之后在 Service 层即可注入并引用这个 RedisTemplate,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import  org.apache.commons.lang3.StringUtils;
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.dao.DataAccessException;
import  org.springframework.data.redis.connection.RedisConnection;
import  org.springframework.data.redis.core.RedisCallback;
import  org.springframework.data.redis.core.RedisTemplate;
import  org.springframework.stereotype.Repository;
 
import  java.io.*;
 
/**
  * Created by fengdezitai on 2016/9/29.
  */
@Repository
public  class  RedisClusterCache {
 
     @Autowired
     private  RedisTemplate clusterRedisTemplate;
 
 
     public  void  put(Object key, Object value) {
         if ( null  == value) {
             return ;
         }
 
         if (value  instanceof  String) {
             if (StringUtils.isEmpty(value.toString())) {
                 return ;
             }
         }
 
         // TODO Auto-generated method stub
         final  String keyf = key +  "" ;
         final  Object valuef = value;
         final  long  liveTime =  86400 ;
 
         clusterRedisTemplate.execute( new  RedisCallback<Long>() {
             public  Long doInRedis(RedisConnection connection)
                     throws  DataAccessException {
                 byte [] keyb = keyf.getBytes();
                 byte [] valueb = toByteArray(valuef);
                 connection.set(keyb, valueb);
                 if  (liveTime >  0 ) {
                     connection.expire(keyb, liveTime);
                 }
                 return  1L;
             }
         });
     }
 
     public  Object get(Object key) {
         final  String keyf = (String) key;
         Object object;
         object = clusterRedisTemplate.execute( new  RedisCallback<Object>() {
             public  Object doInRedis(RedisConnection connection)
                     throws  DataAccessException {
 
                 byte [] key = keyf.getBytes();
                 byte [] value = connection.get(key);
                 if  (value ==  null ) {
                     return  null ;
                 }
                 return  toObject(value);
 
             }
         });
 
         return  object;
     }
 
     /**
      * 描述 : <byte[]转Object>. <br>
      * <p>
      * <使用方法说明>
      * </p>
      *
      * @param bytes
      * @return
      */
     private  Object toObject( byte [] bytes) {
         Object obj =  null ;
         try  {
             ByteArrayInputStream bis =  new  ByteArrayInputStream(bytes);
             ObjectInputStream ois =  new  ObjectInputStream(bis);
             obj = ois.readObject();
             ois.close();
             bis.close();
         catch  (IOException ex) {
             ex.printStackTrace();
         catch  (ClassNotFoundException ex) {
             ex.printStackTrace();
         }
         return  obj;
     }
 
     private  byte [] toByteArray(Object obj) {
         byte [] bytes =  null ;
         ByteArrayOutputStream bos =  new  ByteArrayOutputStream();
         try  {
             ObjectOutputStream oos =  new  ObjectOutputStream(bos);
             oos.writeObject(obj);
             oos.flush();
             bytes = bos.toByteArray();
             oos.close();
             bos.close();
         catch  (IOException ex) {
             ex.printStackTrace();
         }
         return  bytes;
     }
}

最后在 Controller 中调用即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Controller
@RequestMapping (value =  "redisCluster" )
public  class  RedisClusterController {
 
     @Autowired
     private  RedisClusterCache redisClusterCache;
 
     @RequestMapping (value =  "clusterSave" ,method = {RequestMethod.GET,RequestMethod.POST})
     @ResponseBody
     public  Object clusterSave(){
         //redisClusterCache.put("cluster","save cluster");
         Token token =  new  Token();
         token.setExpires_in( 1000 );
         token.setAccess_token( "hello world" );
         redisClusterCache.put( "token" ,token);
         return  "ok" ;
     }
 
     @RequestMapping (value =  "getKey" ,method = RequestMethod.GET)
     @ResponseBody
     public  Object getCluster(String key){
         Object val = redisClusterCache.get(key);
         return  val;
     }
} 

注意事项:

  • 版本问题,如果用 spring-data-redis 做集成操作 Reids 集群,只有 spring-data-redis 目前最新版本1.7才包含对集群的操作,而最新的 spring-data-redis 中的某些功能对 Spring mvc 的版本也有些限制,所以尽量选择高版本的 Spring mvc 对应。
  • 如果存储的value值是一个实体对象,那么一定要实现 Serializable 接口
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值