SpringBoot入門建站全系列(十四)集成Redis緩存

SpringBoot入門建站全系列(十四)集成Redis緩存

一、概述

本地緩存,就是使用應用內使用本地內存將數(shù)據(jù)暫緩存儲,一般數(shù)據(jù)庫的查詢如果不怎么改動,可以用本地緩存暫存。

遠程緩存,比如redis,就是第三方緩存服務器,不是在當前應用的,需要用過tcp請求去獲得的緩存。

Redis是一個開源(BSD許可)的內存數(shù)據(jù)結構存儲,用作數(shù)據(jù)庫,緩存和消息代理。
簡單來說,它是一個以(key,value)的形式存儲數(shù)據(jù)的數(shù)據(jù)庫.

官網:https://redis.io/download 去下載對應的版本。

Spring已經為我們對Redis做了很好的封裝,我們需要做的就是配置和Sercice的調用。

首發(fā)地址:
品茗IT-同步發(fā)布

品茗IT 提供在線支持:

一鍵快速構建Spring項目工具

一鍵快速構建SpringBoot項目工具

一鍵快速構建SpringCloud項目工具

一站式Springboot項目生成

Mysql一鍵生成Mybatis注解Mapper

如果大家正在尋找一個java的學習環(huán)境,或者在開發(fā)中遇到困難,可以加入我們的java學習圈,點擊即可加入,共同學習,節(jié)約學習時間,減少很多在學習中遇到的難題。

二、配置

本文假設你已經引入spring-boot-starter-web。已經是個SpringBoot項目了,如果不會搭建,可以打開這篇文章看一看《SpringBoot入門建站全系列(一)項目建立》。

2.1 Maven依賴

這里要訪問數(shù)據(jù)庫進行緩存,所以要依賴數(shù)據(jù)庫相關jar包,同時要依賴ehcache。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

不配置commons-pool2,啟動可能會報錯,如果你引入了數(shù)據(jù)源相關jar包,這個jar包一般都會被引入的。

2.2 配置文件

在application.properties 中需要添加下面的配置:

spring.redis.database=0
spring.redis.host=192.168.0.49
spring.redis.port=6379
spring.redis.password=test|test
spring.redis.lettuce.pool.max-active=10
spring.redis.lettuce.pool.max-wait=1000
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=5
spring.redis.timeout=1000

這里的redis指定了使用lettuce做redis的連接池,也可以使用jedis。

lettuce和jedis的區(qū)別是,lettuce更屌一點,支持pipeline,但是如果你的redis不支持pipeline,還是用jedis吧,以免被坑。

2.3 替換lettuce,使用jedis

maven依賴修改:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

配置文件修改:

spring.redis.database=0
spring.redis.host=192.168.0.49
spring.redis.port=6379
spring.redis.password=test|test
spring.redis.jedis.pool.max-active=10
spring.redis.jedis.pool.max-wait=1000
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.min-idle=5
spring.redis.timeout=1000

三、Redis配置

配置RedisTemplate,以請求遠程redis。

package com.cff.springbootwork.redis;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
        redisTemplate.setConnectionFactory(factory);   //   key序列化方式;(不然會出現(xiàn)亂碼;),但是如果方法上有Long等非String類型的話,會報類型轉換錯誤;   //   所以在沒有自己定義key生成策略的時候,以下這個代碼建議不要這么寫,可以不配置或者自己實現(xiàn)ObjectRedisSerializer   //   或者JdkSerializationRedisSerializer序列化方式;
        RedisSerializer<String> redisSerializer =  new StringRedisSerializer();  //   Long類型不可以會出現(xiàn)異常信息;
        redisTemplate.setKeySerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(redisSerializer);
        return redisTemplate;
    }
}


以上的Serializer,是配置redis的key的序列化和反序列化策略。這里用StringRedisSerializer就是把key當成一個字符串來序列化。

四、Redis請求大全

下面的RedisService基本上涵蓋了redis的所有操作:

RedisService:

package com.cff.springbootwork.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class RedisService {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 指定緩存失效時間
     *
     * @param key
     *            鍵
     * @param time
     *            時間(秒)
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根據(jù)key 獲取過期時間
     *
     * @param key
     *            鍵 不能為null
     * @return 時間(秒) 返回0代表為永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判斷key是否存在
     *
     * @param key
     *            鍵
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 刪除緩存
     *
     * @param key
     *            可以傳一個值 或多個
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    // ============================String=============================

    /**
     * 普通緩存獲取
     *
     * @param key
     *            鍵
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通緩存放入
     *
     * @param key
     *            鍵
     * @param value
     *            值
     * @return true成功 false失敗
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 普通緩存放入并設置時間
     *
     * @param key
     *            鍵
     * @param value
     *            值
     * @param time
     *            時間(秒) time要大于0 如果time小于等于0 將設置無限期
     * @return true成功 false 失敗
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 遞增
     *
     * @param key
     *            鍵
     * @return
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("遞增因子必須大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 遞減
     *
     * @param key
     *            鍵
     * @return
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("遞減因子必須大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    // ================================Map=================================

    /**
     * HashGet
     *
     * @param key
     *            鍵 不能為null
     * @param item
     *            項 不能為null
     * @return 值
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 獲取hashKey對應的所有鍵值
     *
     * @param key
     *            鍵
     * @return 對應的多個鍵值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     *
     * @param key
     *            鍵
     * @param map
     *            對應多個鍵值
     * @return true 成功 false 失敗
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并設置時間
     *
     * @param key
     *            鍵
     * @param map
     *            對應多個鍵值
     * @param time
     *            時間(秒)
     * @return true成功 false失敗
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
     *
     * @param key
     *            鍵
     * @param item
     *            項
     * @param value
     *            值
     * @return true 成功 false失敗
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
     *
     * @param key
     *            鍵
     * @param item
     *            項
     * @param value
     *            值
     * @param time
     *            時間(秒) 注意:如果已存在的hash表有時間,這里將會替換原有的時間
     * @return true 成功 false失敗
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 刪除hash表中的值
     *
     * @param key
     *            鍵 不能為null
     * @param item
     *            項 可以使多個 不能為null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判斷hash表中是否有該項的值
     *
     * @param key
     *            鍵 不能為null
     * @param item
     *            項 不能為null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash遞增 如果不存在,就會創(chuàng)建一個 并把新增后的值返回
     *
     * @param key
     *            鍵
     * @param item
     *            項
     * @param by
     *            要增加幾(大于0)
     * @return
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash遞減
     *
     * @param key
     *            鍵
     * @param item
     *            項
     * @param by
     *            要減少記(小于0)
     * @return
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    // ============================set=============================

    /**
     * 根據(jù)key獲取Set中的所有值
     *
     * @param key
     *            鍵
     * @return
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根據(jù)value從一個set中查詢,是否存在
     *
     * @param key
     *            鍵
     * @param value
     *            值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將數(shù)據(jù)放入set緩存
     *
     * @param key
     *            鍵
     * @param values
     *            值 可以是多個
     * @return 成功個數(shù)
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 將set數(shù)據(jù)放入緩存
     *
     * @param key
     *            鍵
     * @param time
     *            時間(秒)
     * @param values
     *            值 可以是多個
     * @return 成功個數(shù)
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 獲取set緩存的長度
     *
     * @param key
     *            鍵
     * @return
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值為value的
     *
     * @param key
     *            鍵
     * @param values
     *            值 可以是多個
     * @return 移除的個數(shù)
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    // ===============================list=================================

    /**
     * 獲取list緩存的內容
     *
     * @param key
     *            鍵
     * @param start
     *            開始
     * @param end
     *            結束 0 到 -1代表所有值
     * @return
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 獲取list緩存的長度
     *
     * @param key
     *            鍵
     * @return
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通過索引 獲取list中的值
     *
     * @param key
     *            鍵
     * @param index
     *            索引 index>=0時, 0 表頭,1 第二個元素,依次類推;index<0時,-1,表尾,-2倒數(shù)第二個元素,依次類推
     * @return
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 將list放入緩存
     *
     * @param key
     *            鍵
     * @param value
     *            值
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將list放入緩存
     *
     * @param key
     *            鍵
     * @param value
     *            值
     * @param time
     *            時間(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將list放入緩存
     *
     * @param key
     *            鍵
     * @param value
     *            值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將list放入緩存
     *
     * @param key
     *            鍵
     * @param value
     *            值
     * @param time
     *            時間(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根據(jù)索引修改list中的某條數(shù)據(jù)
     *
     * @param key
     *            鍵
     * @param index
     *            索引
     * @param value
     *            值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N個值為value
     *
     * @param key
     *            鍵
     * @param count
     *            移除多少個
     * @param value
     *            值
     * @return 移除的個數(shù)
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}


五、測試

寫一個簡單的get/set測試下redis:

RedisRest :

詳細完整的代碼,可以訪問品茗IT-博客《SpringBoot入門建站全系列(十四)集成Redis緩存》進行查看

快速構建項目

Spring組件化構建

SpringBoot組件化構建

SpringCloud服務化構建

喜歡這篇文章么,喜歡就加入我們的Java學習圈(點擊加入或下方掃碼)一起討論SpringBoot技術吧!

品茗IT交流群

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • NOSQL類型簡介鍵值對:會使用到一個哈希表,表中有一個特定的鍵和一個指針指向特定的數(shù)據(jù),如redis,volde...
    MicoCube閱讀 4,166評論 2 27
  • Spring Boot 2.0 需要 Java 8 或更高版本。不再支持 Java 6 和 7 了 在 Sprin...
    架構技術專欄閱讀 2,135評論 0 50
  • “最佩服的人就是,他能聽到自己內心的聲音,又從不去貶低他人的夢想。能聽到自己內心的聲音,代表他深知自己想要的,能不...
    信仰N閱讀 251評論 0 0
  • 最近家里的老鼠太猖狂了,家里的玉米袋子麥子袋子都被捅爛了,地上撒的玉米粒和麥子粒到處是,把人真是氣壞了,所...
    靖宇軒逸閱讀 414評論 0 0
  • 心在飛揚 原創(chuàng)/愛染年華/心在飛 春風暖心赴征程 努力拼搏道不孤 八戒歸來輕淡網 重整雄風紅塵渡
    愛染年華閱讀 339評論 0 3

友情鏈接更多精彩內容