SpringBoot中搭建Redis緩存

(一)SpringBoot中搭建Redis緩存

這篇文章講述如何在Springboot中搭建redis,按照以下步驟進行


 1)、以下鏈接 是如何在window本地搭建redis進行測試

https://blog.csdn.net/qq_29434911/article/details/79876580

注意:在導入jedis-2.6.2.jar、spring-data-redis-1.4.2.RELEASE.jar  如果你下載的版本太低可能會提示版本有誤(解決方法只要重新下一個高版本就行了),我這個版本應該是沒錯的。之前

spring-data-redis-1.4.2.RELEASE.jar 我是下載1.0.0所以太低了。

 2)在Springboot運用redis方法進行緩存操作

           第一步:在pom.xml文件中配置redis

		<!--redis配置-->  
		<dependency>  
		    <groupId>org.springframework.boot</groupId>  
		    <artifactId>spring-boot-starter-redis</artifactId>  <!-- 可以不需要加入版本號 -->
		</dependency>  
		
		 <dependency>
     		<groupId>redis.clients</groupId>
     		<artifactId>jedis</artifactId>
    		 <version>2.5.2</version>
 		</dependency>


         第二步:初始化Redis連接池 ,操作redis

          CacheKit.java:         

package com.zcwl.redis;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.exceptions.JedisConnectionException;

public class CacheKit {
	
	private static Logger logger = LoggerFactory.getLogger(CacheKit.class);  
	
	private List<JSONObject> resultList;  
	
	private static JedisPool pool;  
	
	
	 /** 
     * 初始化Redis連接池 
     */  
    private static void initializePool() {  
        //redisURL 與 redisPort 的配置文件  
  
        JedisPoolConfig config = new JedisPoolConfig();  
        //設置最大連接數(100個足夠用了,沒必要設置太大)  
        config.setMaxTotal(100);  
        //最大空閒連接數  
        config.setMaxIdle(10);  
        //獲取Jedis連接的最大等待時間(50秒)   
        config.setMaxWaitMillis(50 * 1000);  
        //在獲取Jedis連接時,自動檢驗連接是否可用  
        config.setTestOnBorrow(true);  
        //在將連接放回池中前,自動檢驗連接是否有效  
        config.setTestOnReturn(true);  
        //自動測試池中的空閒連接是否都是可用連接  
        config.setTestWhileIdle(true);
        //創建連接池  
        //pool = new JedisPool(config, "120.88.166.244",6379);	//連接阿里雲服務器上面的緩存(如果本地在使用地址,本地運行將會把本地緩存數據同步在線上緩存中)
        pool = new JedisPool(config, "127.0.0.1",6379);	//本地緩存(更新需要將這個註釋起來,解開上面地址)
    }
    

    /** 
     * 多線程環境同步初始化(保證項目中有且僅有一個連接池) 
     */  
    private static synchronized void poolInit() {  
        if (null == pool) {  
            initializePool();  
        }  
    } 
    
    /** 
     * 獲取Jedis實例 
     */  
    private static Jedis getJedis() {  
        if (null == pool) {  
            poolInit();  
        }  
  
        int timeoutCount = 0;  
        while (true) {
            try {  
                if (null != pool) {  
                    return pool.getResource();  
                }  
            } catch (Exception e) {  
                if (e instanceof JedisConnectionException) {  
                    timeoutCount++;  
                    logger.warn("getJedis timeoutCount={}", timeoutCount);  
                    if (timeoutCount > 3) {  
                        break;  
                    }  
                } else {  
                   /* logger.warn("jedisInfo ... NumActive=" + pool.getResource().get("")
                            + ", NumIdle=" + pool.getNumIdle()  
                            + ", NumWaiters=" + pool.getNumWaiters()  
                            + ", isClosed=" + pool.isClosed());  */
                	logger.warn(pool.getResource()+"//"+pool);
                    logger.error("GetJedis error,", e);  
                    break;  
                }  
            }
            break;  
        }
        return null;  
    }  
    
    
    /** 
     * 釋放Jedis資源 
     * 
     * @param jedis 
     */  
    private static void returnResource(Jedis jedis) {  
        if (null != jedis) {  
            pool.returnResourceObject(jedis);  
        }  
    }
    
    /** 
     * 絕對獲取方法(保證一定能夠使用可用的連接獲取到 目標數據) 
     * Jedis連接使用後放回  
     * @param key 
     * @return 
     */  
    private String safeGet(String key) {  
        Jedis jedis = getJedis();  
        while (true) {  
            if (null != jedis) {  
                break;  
            } else {  
                jedis = getJedis();  
            }  
        }  
        String value = jedis.get(key);  
        returnResource(jedis);  
        return value;  
    }
    
    
    /** 
     * 絕對設置方法(保證一定能夠使用可用的鏈接設置 數據) 
     * Jedis連接使用後返回連接池 
     * @param key 
     * @param time 
     * @param value 
     */  
    public void safeSet(String key, int time, String value) {  
        Jedis jedis = getJedis();  
        while (true) {  
            if (null != jedis) {  
                break;  
            } else {  
                jedis = getJedis();  
            }  
        }  
        jedis.setex(key, time, value);  
        returnResource(jedis);  
    }  
    
    /** 
     * 絕對刪除方法(保證刪除絕對有效) 
     * Jedis連接使用後返回連接池</span> 
     * @param key 
     */  
    private void safeDel(String key) {  
        Jedis jedis = getJedis();  
        while (true) {  
            if (null != jedis) {  
                break;  
            } else {  
                jedis = getJedis();  
            }  
        }  
        jedis.del(key);  
        returnResource(jedis);  
    }
    
    /**
     * 清除所有緩存
     */
    private static void clearCache(){
    	CacheKit kit = new CacheKit();
    	Jedis jedis = getJedis();  
    	while (true) {  
    		if (null != jedis) {  
    			break;  
    		} else {  
    			jedis = getJedis();  
    		}  
    	}
       //PS:redis默認有一些key已經存在裏面,不能刪除,所以後面在添加key的時候用一個統一的標識符這樣將自己添加的刪除
    	Iterator it = jedis.keys("redis*").iterator();	//帶*號清除所有,如果寫有前綴就匹配出來sy*
    	while (it.hasNext()) {
    		String key = (String) it.next();
    		kit.delByCache(key);	//刪除key
    		logger.info(new Date()+":將redis緩存"+key+"值刪除成功!");
    	}
    	returnResource(jedis); 
	}
    
    
    /**自定義的一些 get set del 方法,方便使用  在其他地方直接調用**/  
    public JSONObject getByCache(String key) {
        String result = safeGet(key);  
        if (result != null) {  
            return (JSONObject) JSONObject.parse(result);  
        }  
        return null;  
    }
  
    public String getByCacheToString(String key) {
        String result = safeGet(key);  
        if (result != null) {  
            return result;  
        }  
        return null;  
  
    }  
  
    public List<JSONObject> getArrayByCache(String key) {  
        String result = safeGet(key);  
        if (result != null) {  
            resultList = JSONArray.parseArray(result, JSONObject.class);  
            return resultList;  
        }  
        return null;  
    }  
  
    public JSONArray getJSONArrayByCache(String key) {  
        String result = safeGet(key);  
        if (result != null) {  
            return JSONArray.parseArray(result);  
        }  
        return null;  
    }  
  
    public void setByCache(String key, String s) {  
        safeSet(key, 86400, s);  
    }  
  
    public void setByCacheOneHour(String key, String s) {  
        safeSet(key, 3600, s);  
    }  
  
    public void setByCacheOneHour(String key, List<JSONObject> json) {  
        safeSet(key, 86400, JSONObject.toJSONString(json));  
        resultList = json;  
    }  
  
    public void setByCache(String key, JSONObject json) {  
        safeSet(key, 86400, JSONObject.toJSONString(json));  
    }  
  
    public void setByCache(String key, List<JSONObject> list) {  
        safeSet(key, 86400, JSONObject.toJSONString(list));  
        resultList = list;  
    }  
  
    public void setByCache(String key, JSONArray array) {  
        safeSet(key, 86400, JSONArray.toJSONString(array));  
    }  
  
    public void setByCacheCusTime(String key, String s, int time) {  
        safeSet(key, time, s);  
    }  
  
    public void delByCache(String key) {
    	//該方法刪除指定的key
        if (null != safeGet(key)) {  
            safeDel(key);  
        }  
    }
    
    //該方法用來清除所有相關redis的key
    public void delRedisRelevantKey(){
    	clearCache();
    }
  
    public JSONObject toJSON(JSONObject db) {
        return (JSONObject) JSONObject.toJSON(db);  
    }  
  
    public List<JSONObject> toJSON(List<JSONObject> list) {
        List<JSONObject> json = new ArrayList<>();  
        for (JSONObject aList : list) {  
            json.add((JSONObject) JSONObject.toJSON(aList));  
        }
        return json;  
    }  
  
    public boolean notNull() {
        return resultList != null && resultList.size() > 0;  
    }  
  
    public List<JSONObject> getResult() {
        return resultList;
    }
    
    public static void main(String[] args) {
    	//clearCache();  到這裏自己去測試一下是否可以
	}

}

之前看過其它大神的文章,都是將緩存地址放到application.properties、還有什麼application.yml裏面,但是我試過到我這裏取不到地址,試過很多方式取不到所以才決定地址放到外面,我個人覺得影響應該不會很大。

裏面也寫了很多公共方法方便調用管理。如果這裏測試沒問題那就運用到業務流程存儲數據。

RedisUtil.java   

這個類用來寫redis公共方法

package com.zcwl.redis;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zcwl.goods.dto.GoodsBrand;

import net.sf.json.JSONObject;

/**
 * redis緩存公共方法
 * @author Liangth
 */

public class RedisUtil {
	
	private static Logger log = LoggerFactory.getLogger(RedisUtil.class);  
	
	//redisSyIndexBrand    命名分解  redis(用來清除緩存時候,查找) SY(代表首頁比如商城:SC) 後面隨機變化
	private static final String index_Brand = "redisSyIndexBrand";		//首頁推薦品牌
	
	private static CacheKit kit = new CacheKit();
	
	/**
	 * 首頁推薦品牌
	 * start
	 */
	//緩存數據
	public void saveIndexBrand(List<GoodsBrand> goodsBrand){
		try {
			List<JSONObject> array = new ArrayList<JSONObject>();
			for (int i = 0; i < goodsBrand.size(); i++) {
				JSONObject object = new JSONObject();
				object.put("id", goodsBrand.get(i).getId());
				object.put("brandName", goodsBrand.get(i).getBrandName());
				object.put("brandImg", goodsBrand.get(i).getBrandImg());
				if(goodsBrand.get(i).getCountryImgUrl()==null){
					object.put("countryImgUrl", "");	
				}else{
					object.put("countryImgUrl", goodsBrand.get(i).getCountryImgUrl());
				}
				object.put("specialType", goodsBrand.get(i).getSpecialType());
				array.add(object);
			}
			kit.setByCache(index_Brand, array.toString());
			log.info(new Date()+":緩存數據首頁推薦品牌成功。key:"+index_Brand);
		} catch (Exception e) {
			log.error("數據緩存首頁推薦品牌異常,請檢查RedisUtil方法!。key:"+index_Brand);
		}
	}
	
	//讀取緩存
	public List<GoodsBrand> readIndexBrand(){
		List<GoodsBrand> goodsBrand = new ArrayList<GoodsBrand>();
		try {
			List<com.alibaba.fastjson.JSONObject> list = kit.getArrayByCache(index_Brand);
			for (int i = 0; i < list.size(); i++) {
				GoodsBrand brand = new GoodsBrand();
				brand.setId(Integer.parseInt(list.get(i).get("id").toString()));
				brand.setBrandName(list.get(i).get("brandName").toString());
				brand.setBrandImg(list.get(i).get("brandImg").toString());
				if(list.get(i).get("countryImgUrl").toString() != null){
					brand.setCountryImgUrl(list.get(i).get("countryImgUrl").toString());
				}else{
					brand.setCountryImgUrl("");
				}
				brand.setSpecialType(list.get(i).get("specialType").toString());
				goodsBrand.add(brand);
			}
			log.info(new Date()+":讀取緩存數據首頁推薦品牌成功。key:"+index_Brand);
		} catch (Exception e) {
			// TODO: handle exception
			log.error("讀取緩存首頁推薦品牌異常,請檢查RedisUtil方法!。key:"+index_Brand);
		}
		return goodsBrand;
	}
	
	/**
	 * end
	 */
	
}

注意:redis數據結構以key-value存儲,所以將自己的數據結構轉換成這種方式去存儲,


3):在控制器裏面去調用上面接口


這裏應該都看得懂,我就不解釋啦。裏面有打印那些提示,在控制檯查看緩存功能是不是成功了!


4)清除緩存

我這裏暫時沒有做到數據庫和redis數據的實時同步。

現在有兩個方案可以更新:

            (1)如果後臺改動數據需要馬上更新,那我們就可以在前臺觸發事件來調用後臺清理緩存接口

            (2)還有設置一個定時器調用接口,到某個時間段來同步數據




阿里雲服務器安裝Redis及基本配置

請關注下一篇文章



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章