首頁  >  文章  >  web前端  >  Java Spring mvc 操作 Redis 及 Redis 集群

Java Spring mvc 操作 Redis 及 Redis 集群

高洛峰
高洛峰原創
2017-05-26 14:40:391468瀏覽

關於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版本,如下:

      redis.clients      jedis      2.9.0  

操作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 jedisClusterNodes = new HashSet();
        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();
    }
}  

ring mvc 操作Redis ,首先當然要搭好Spring mvc 框架了。以下是假設 Spring mvc 環境已經架好的情況下。本例中 Spring 版本為 4.3.2 RELEASE。關於Spring 的maven 引用如下:

4.3.2.RELEASE 

    
          org.springframework      spring-core      ${spring.version}                        commons-logging          commons-logging                   
          org.springframework      spring-web      ${spring.version}     
          org.springframework      spring-oxm      ${spring.version}     
          org.springframework      spring-tx      ${spring.version}     
          org.springframework      spring-jdbc      ${spring.version}     
          org.springframework      spring-webmvc      ${spring.version}                        commons-logging          commons-logging                   
          org.springframework      spring-aop      ${spring.version}     
          org.springframework      spring-context-support      ${spring.version}     
 
          org.springframework      spring-test      ${spring.version}

操作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.
 */
@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 實作如下:

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

      org.springframework.data      spring-data-redis      1.7.2.RELEASE

使用spring-data-redis ,即省去了自己實現注入的過程,透過它提供的一些配置,即可實現連接池配置、 RedisTemplate 設定、JedisConnectionFactory 設定;透過 JedisConnectionFactory 可設定連接池參數、redis 伺服器、連接埠、密碼、逾時時間、database索引等;RedisTemplate 即註入的bean ,可以使用 RedisTemplate 自動注入的實體進行redis 的一系列操作,具體來看設定;

redis 服務屬性設定檔:

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:

                                    
                                    -->
                     
                                                 
                                    -->

spring-data-redis xml 設定檔 redis-context.xml:

  

之後在spring 設定檔中引用以上檔案:

rrrereee

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.*;
 
@Repository
public class RedisCache {
  
    @Resource(name = "cacheRedisTemplate")
    private RedisTemplate

最後在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 自行實現(區別於下面的參考注入-data-redis)

把前面的 JedisClusterClient 程式碼拿過來引用即可,只要實作一個存取Redis 的Service ,就可以整合到Spring mvc 。 Service 程式碼如下:

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 即可

@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 套件和前面一致,之所以引用和前面一致,之所以引用data-redis 1.7.2.RELEASE,是因為目前只有這個最新版本才支援叢集操作。

redis 群集服務屬性配置

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

spring-data-redis xml 叢集設定檔 redis-cluster-context.xml

<br/>

之後在Spring 設定檔中引用

<br/>

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

之後在Spring 設定檔中引用

錯reee ,redisClusterConfig 設定了Redis 叢集的各個節點(節點host 和port 最好寫在屬性設定檔中),叢集搭建可見我的 另一篇部落格 。然後下面和單機配置一樣了,一對 JedisConnectionFactory 和 RedisTemplate 。

之後在 Service 層即可注入並引用這個 RedisTemplate,程式碼如下:

@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;
    }
} 

最後在 Controller 中呼叫即可

rrreee

注意事項:

版本問題,如果用 spring-data-redis 做集成操作Reids 集群,只有 spring-data-redis 目前最新版本1.7才包含對集群的操作,而最新的 spring-data-redis 中的某些功能對Spring mvc的版本也有些限制,所以盡量選擇高版的 Spring mvc 對應。

如果儲存的value值是一個實體對象,那麼一定要實現 Serializable 介面

【相關推薦】

1. 詳解Spring框架註解的用法程式碼實例

詳解Spring框架註解的用法程式碼實例

🎜2. Hibernate的程式碼詳解🎜🎜
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn