你的位置:首页 > Java教程

[Java教程]Java Spring mvc 操作 Redis 及 Redis 集群


 本文原创,转载请注明:http://www.cnblogs.com/fengzheng/p/5941953.html

关于 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版本,如下:

<dependency>   <groupId>redis.clients</groupId>   <artifactId>jedis</artifactId>   <version>2.9.0</version></dependency>  

操作 Redis 单机

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 集群

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 引用如下:

<!-- 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 代码如下:

import org.springframework.stereotype.Service;import util.JedisClient;/** * Created by fengdezitai on 2016/10/9. */@Servicepublic 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 实现如下:

@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:

<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 服务属性配置文件:

redis.maxIdle=300redis.maxWait=3000redis.testOnBorrow=trueredis.host=192.168.31.121redis.port=6379redis.password=passwordredis.timeout=3000

spring-data-redis

<!-- jedis 连接池 配置 -->  <bean id="poolConfig" >    <property name="maxIdle" value="${redis.maxIdle}" />    <property name="maxWaitMillis" value="${redis.maxWait}" />    <property name="testOnBorrow" value="${redis.testOnBorrow}" />  </bean>  <!-- redis服务器中心 -->  <bean id="connectionFactory"  >    <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" >    <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"  >    <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" />  <bean id="cacheRedisTemplate" >    <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 配置文件中引用以上文件:

<import resource="redis-context.

解释一下上面的配置:

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

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

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.*;@Repositorypublic class RedisCache {
   @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 中调用即可

  @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 代码如下:

import org.springframework.stereotype.Service;import util.JedisClusterClient;/** * Created by fengdezitai on 2016/10/13. */@Servicepublic class RedisClusterService {  public void save() throws Exception{    //调用 JedisClusterClient 中的方法    JedisClusterClient jedisClusterClient = JedisClusterClient.getInstance();    try {      jedisClusterClient.SaveRedisCluster();    }catch (Exception e){      throw e;    }  }}

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

@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 集群服务属性配置

redis.maxIdle=300redis.maxWait=3000redis.testOnBorrow=falseredis.timeout=3000

spring-data-redis

<!-- 连接池 配置 -->  <bean id="poolConfig" >    <property name="maxIdle" value="${redis.maxIdle}" />    <property name="maxWaitMillis" value="${redis.maxWait}" />    <property name="testOnBorrow" value="${redis.testOnBorrow}" />  </bean>  <bean id="redisClusterConfig" >    <property name="maxRedirects" value="3"></property>    <property name="clusterNodes">      <set>        <bean >          <constructor-arg name="host" value="192.168.31.245"></constructor-arg>          <constructor-arg name="port" value="7000"></constructor-arg>        </bean>        <bean >          <constructor-arg name="host" value="192.168.31.245"></constructor-arg>          <constructor-arg name="port" value="7001"></constructor-arg>        </bean>        <bean >          <constructor-arg name="host" value="192.168.31.245"></constructor-arg>          <constructor-arg name="port" value="7002"></constructor-arg>        </bean>         <bean >          <constructor-arg name="host" value="192.168.31.210"></constructor-arg>          <constructor-arg name="port" value="7003"></constructor-arg>        </bean>        <bean >          <constructor-arg name="host" value="192.168.31.210"></constructor-arg>          <constructor-arg name="port" value="7004"></constructor-arg>        </bean>        <bean >          <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"     >    <constructor-arg name="clusterConfig" ref="redisClusterConfig" />    <property name="timeout" value="${redis.timeout}" />    <property name="poolConfig" ref="poolConfig"/>  </bean>  <bean name="stringRedisSerializer" />  <bean id="clusterRedisTemplate" >    <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 配置文件中引用

<import resource="redis-cluster-context.

解释以上配置

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

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

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. */@Repositorypublic 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 中调用即可

@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 接口

 




深圳到英国旅游报价到英国旅游要多少钱英国旅游路线英国旅游多少钱跟团英国旅游网东部华侨城什么时候去最好?深圳东部华侨城门票包括什么项目? 3月东部华侨城有什么好玩的?2015深圳东部华侨城最新门票价格? 酒花香里闯魔城 最不可思议的海珠绿道游 佛山南海影视城门票包括什么?中央电视台南海影视城有什么好玩的? 道滘粤晖园怎么走?粤晖园拓展基地自驾攻略? 东莞粤晖园地址?粤晖园拓展基地在哪里? 探秘秀美的闽西“客家神山”冠豸山 秋风起芦花飞 宁波周边四大游芦地推荐 在马尔代夫一定要玩的项目 宁海温泉自驾游指南 香港自由行必看的住宿攻略 11月去云南旅游天气怎样?要带什么? 花都香草世界门票团购多少钱?广州花都香草世界团体票怎么买?_香草世界旅游攻略_香草世界旅游景点 花都香草世界网上订票?广州花都香草世界优惠票多少钱?_香草世界旅游攻略_香草世界旅游景点 八里湖湿地 鸟儿栖息的纯净乐园_白洋淀旅游攻略_白洋淀旅游景点 聆听秋日私语 齐鲁赏秋全攻略_济南旅游攻略_济南旅游景点 MID-85A1C Datasheet MID-85A1C Datasheet MID-85H1C Datasheet MID-85H1C Datasheet MID-86414 Datasheet MID-86414 Datasheet 葡萄牙美食 葡萄牙美食 葡萄牙美食 名山大川图片 名山大川图片 名山大川图片 澳门一天旅游攻略 澳门一天旅游攻略 澳门一天旅游攻略