Spring-Boot2-X集成Redis做緩存

實(shí)戰(zhàn)出真知扯再,作文以記之。

解決的主要痛點(diǎn)

  • 以SpringBoot2.0.2為背景
  • 通用的序列化和反序列化設(shè)置
    使用Jackson2JsonRedisSerializer進(jìn)行序列化與反序列化。
  • 解決緩存中的亂碼問(wèn)題
  • 詳細(xì)的使用說(shuō)明
  • 齊全的使用示例

創(chuàng)建Spring Boot工程

略车猬,詳細(xì)步驟可參考使用STS創(chuàng)建Spring Boot 項(xiàng)目门躯。

添加Maven依賴

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
</dependency>

Redis的配置參數(shù)

在application.properties中加入以下配置參數(shù)

# 緩存時(shí)長(zhǎng)淆党,單位秒
cache.default-exp=72
# 數(shù)據(jù)庫(kù)設(shè)置
spring.redis.database=0
# 宿主機(jī)IP
spring.redis.host=127.0.0.1
# 端口號(hào)
spring.redis.port=6379
# 密碼
spring.redis.password=redis
# 連接超時(shí)時(shí)間 單位 ms(毫秒)
spring.redis.timeout=3000
# 連接池中的最大空閑連接,默認(rèn)值也是8
spring.redis.lettuce.pool.max-idle=100
# 連接池中的最小空閑連接讶凉,默認(rèn)值也是0
spring.redis.lettuce.pool.min-idle=50
# 如果賦值為-1染乌,則表示不限制
spring.redis.lettuce.pool.max-wait=2000

使用注解配置Redis

創(chuàng)建一個(gè)名為RedisConfig的class并繼承CachingConfigurerSupport,注意需要在class上添加@Configuration和@EnableCaching注解懂讯。

import java.lang.reflect.Method;
import java.time.Duration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Value("${cache.default-exp}")
    private long exps;

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.lettuce.pool.min-idle}")
    private int minIdle;

    @Value("${spring.redis.lettuce.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.lettuce.pool.max-wait}")
    private long maxWaitMillis;

    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuffer sb = new StringBuffer();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * RedisTemplate配置
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 使用Jackson2JsonRedisSerializer來(lái)序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer<JSON> serializer = new Jackson2JsonRedisSerializer<JSON>(JSON.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        template.setValueSerializer(serializer);
        template.setHashValueSerializer(serializer);
        // 使用StringRedisSerializer來(lái)序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 生成一個(gè)默認(rèn)配置荷憋,通過(guò)config對(duì)象即可對(duì)緩存進(jìn)行自定義配置
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        // 使用Jackson2JsonRedisSerializer來(lái)序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer<JSON> serializer = new Jackson2JsonRedisSerializer<JSON>(JSON.class);
        // 配置序列化
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer));
        config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));
        // 設(shè)置緩存的默認(rèn)過(guò)期時(shí)間
        config.entryTtl(Duration.ofSeconds(exps));
        // 不緩存空值
        config.disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();
        return cacheManager;
    }
}

緩存使用示例

分別對(duì)@Cacheable、@CachePut和@CacheEvict進(jìn)行了舉例褐望。

@Cacheable(value = "users",key = "#collection.concat(#user.id)")
public void create(String collection, JSONObject  user)  {
  //do something
}

@CacheEvict(value = "users",key = "#collection.concat(#id)")
public void delete(String collection, String id)  {
  //do something
}

@Cacheable(value = "users",key = "#collection.concat(#id)")
public JSONObject getOne(String collection, String id)  {
  //do something
}

注意事項(xiàng)

  • 要緩存的 Java 對(duì)象必須實(shí)現(xiàn) Serializable 接口
  • 在CacheManager對(duì)象中 設(shè)置緩存過(guò)期時(shí)間勒庄,否則緩存對(duì)象將永不過(guò)期
  • 緩存key必須為string類型的值串前,否則需要進(jìn)行類型轉(zhuǎn)換
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市实蔽,隨后出現(xiàn)的幾起案子荡碾,更是在濱河造成了極大的恐慌,老刑警劉巖局装,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坛吁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡铐尚,警方通過(guò)查閱死者的電腦和手機(jī)拨脉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)宣增,“玉大人女坑,你說(shuō)我怎么就攤上這事⊥骋ǎ” “怎么了匆骗?”我有些...
    開(kāi)封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)誉简。 經(jīng)常有香客問(wèn)我碉就,道長(zhǎng),這世上最難降的妖魔是什么闷串? 我笑而不...
    開(kāi)封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任瓮钥,我火速辦了婚禮,結(jié)果婚禮上烹吵,老公的妹妹穿的比我還像新娘碉熄。我一直安慰自己,他們只是感情好肋拔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布锈津。 她就那樣靜靜地躺著,像睡著了一般凉蜂。 火紅的嫁衣襯著肌膚如雪琼梆。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天窿吩,我揣著相機(jī)與錄音茎杂,去河邊找鬼。 笑死纫雁,一個(gè)胖子當(dāng)著我的面吹牛煌往,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播轧邪,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼刽脖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悼粮!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起曾棕,我...
    開(kāi)封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扣猫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后翘地,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體申尤,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年衙耕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昧穿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡橙喘,死狀恐怖时鸵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情厅瞎,我是刑警寧澤饰潜,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站和簸,受9級(jí)特大地震影響彭雾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锁保,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一薯酝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧爽柒,春花似錦吴菠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至穴亏,卻和暖如春蜂挪,著一層夾襖步出監(jiān)牢的瞬間重挑,已是汗流浹背嗓化。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谬哀,地道東北人刺覆。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像史煎,于是被迫代替她去往敵國(guó)和親谦屑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驳糯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 李笑來(lái)一直強(qiáng)調(diào)概念的重要性,這兩天參加培訓(xùn)氢橙,對(duì)“面向?qū)ο蟆边@個(gè)概念進(jìn)行了深入的思考酝枢。 幾乎每一本“xx從入門到精通...
    張永勝_永往直前閱讀 273評(píng)論 0 1
  • 吳縣有位縣令,平素剛介耿直悍手,頗有名聲帘睦。而這吳縣的風(fēng)俗,極為重視城隍神坦康,每到城隍誕辰竣付,則所有百姓都得出錢集資做神會(huì)。...
    梵溫2閱讀 494評(píng)論 0 0
  • 大清早的一起床滞欠,發(fā)呆古胆、刷牙、洗臉筛璧、洗鼻逸绎、燒水、蒸包子夭谤。清清爽爽好不快活桶良。然后就打開(kāi)電腦就在碼字。別誤會(huì)哦沮翔,我雖文藝...
    sonxbb閱讀 161評(píng)論 0 0