1. 程式人生 > 其它 >Spring Boot使用——整合Redis

Spring Boot使用——整合Redis

環境

  • Java8
  • redis2.8

配置如下

  • pom檔案
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
  • yml配置檔案
redis:
  host: XXXXXX
  port: XXXX
  password: XXXXXXX
  ssl: XXXX
  lettuce:
    pool:
      max-total: 100      #    最大連線數
      max-active: 200
      min-idle: 20        #   最小空閒連線數
      max-idle: 200
      max-wait-millis: 10000   #   當池內沒有可用的連線時,最大等待時間
  • 自定義Redis屬性類
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; //redis: // host: 127.0.0.1 // port: 6379 // password: // lettuce: // pool: // max-total: 100 # 最大連線數 // max-active: 200 // min-idle: 20 # 最小空閒連線數 // max-idle: 200 // max-wait-millis: 10000 # 當池內沒有可用的連線時,最大等待時間 @Component @ConfigurationProperties(
"redis") public class RedisProperties { private final RedisLettuceProperties lettuce = new RedisLettuceProperties(); private String host; private int port; private String password; private boolean ssl; RedisProperties() { // // initialize the default values // this.host = "127.0.0.1"; this.port = 6379; this.password = ""; this.ssl = true; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getHost() { return host; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isSsl() { return ssl; } public void setSsl(boolean ssl) { this.ssl = ssl; } public void setHost(String host) { this.host = host; } public RedisLettuceProperties getLettuce() { return this.lettuce; } // public static class RedisLettuceProperties { private final RedisLettucePoolProperties pool = new RedisLettucePoolProperties(); RedisLettuceProperties() { } public RedisLettucePoolProperties getPool() { return this.pool; } // redis.jedis.pool public static class RedisLettucePoolProperties { private int maxTotal; // 最大連線數 private int maxActive; private int minIdle; // 最小空閒連線數 private int maxIdle; // private int maxWaitMillis; // 毫秒;當池內沒有可用的連線時,最大等待時間 RedisLettucePoolProperties() { maxTotal = 100; maxActive = 200; minIdle = 20; maxIdle = 200; maxWaitMillis = 10000; } public int getMaxTotal() { return maxTotal; } public void setMaxTotal(int maxTotal) { this.maxTotal = maxTotal; } public int getMaxActive() { return maxActive; } public void setMaxActive(int maxActive) { this.maxActive = maxActive; } public int getMinIdle() { return minIdle; } public void setMinIdle(int minIdle) { this.minIdle = minIdle; } public int getMaxIdle() { return maxIdle; } public void setMaxIdle(int maxIdle) { this.maxIdle = maxIdle; } public int getMaxWaitMillis() { return maxWaitMillis; } public void setMaxWaitMillis(int maxWaitMillis) { this.maxWaitMillis = maxWaitMillis; } } } }
  • 自定義Config
package com.canaan.minemanage.config;

import com.canaan.minemanage.property.RedisProperties;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.RedisCacheManager;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


@Configuration
@EnableCaching
@EnableRedisRepositories
public class RedisConfig extends CachingConfigurerSupport {
    private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);

    @Autowired
    RedisProperties redisProperties;

    /**
     * 自定義Lettuce工廠
     *
     * @param genericObjectPoolConfig
     * @return
     */
    @Bean
    LettuceConnectionFactory lettuceConnectionFactory(GenericObjectPoolConfig genericObjectPoolConfig) {
        String host = redisProperties.getHost();
        int port = redisProperties.getPort();
        String password = redisProperties.getPassword();
        boolean ssl = redisProperties.isSsl();

        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(port);
        redisStandaloneConfiguration.setPassword(password);
        logger.info("RedisStandaloneConfiguration: {}:{}:{}",
                redisProperties.getHost(), redisProperties.getPort(), redisProperties.getPassword());


        LettucePoolingClientConfiguration clientConfig = null;
        if (ssl) {
            clientConfig = LettucePoolingClientConfiguration
                    .builder()
                    .poolConfig(genericObjectPoolConfig)
                    .useSsl()
                    .build();
        } else {
            clientConfig = LettucePoolingClientConfiguration
                    .builder()
                    .poolConfig(genericObjectPoolConfig)
                    .build();
        }

        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
        return factory;
    }

    /**
     * GenericObjectPoolConfig 連線池配置
     *
     * @return
     */
    @Bean
    public GenericObjectPoolConfig genericObjectPoolConfig() {
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());
        genericObjectPoolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle());
        genericObjectPoolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());
        genericObjectPoolConfig.setMaxWaitMillis(redisProperties.getLettuce().getPool().getMaxWaitMillis());
        return genericObjectPoolConfig;
    }


    /**
     * 選擇redis作為預設快取工具
     *
     * @param lettuceConnectionFactory
     * @return
     */
    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisCacheManager redisCacheManager = RedisCacheManager.create(lettuceConnectionFactory);
        return redisCacheManager;
    }

    /**
     * 自定義快取key生成規則
     *
     * @return
     */
//    @Override
//    @Bean
//    public KeyGenerator keyGenerator() {
//        return (target, method, params) -> {
//            StringBuilder stringBuilder = new StringBuilder();
//            for (int index = 1; index <= params.length; index++) {
//                stringBuilder.append(params[index - 1].toString());
//                if (index != params.length) {
//                    stringBuilder.append("-");
//                }
//            }
//            return stringBuilder.toString();
//        };
//    }


    /**
     * retemplate相關配置
     *
     * @param lettuceConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(lettuceConnectionFactory);

        // 配置連線工廠
        template.setConnectionFactory(lettuceConnectionFactory);

        //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值(預設使用JDK的序列化方式)
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修飾符範圍,ANY是都有包括private和public
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化輸入的型別,類必須是非final修飾的,final修飾的類,比如String,Integer等會跑出異常
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        //POJO無public的屬性或方法時,不報錯
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        //null值欄位不顯示
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //美化JSON輸出
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);

        jacksonSeial.setObjectMapper(objectMapper);

        // 值採用json序列化
        template.setValueSerializer(jacksonSeial);
        //使用StringRedisSerializer來序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());

        // 設定hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();

        return template;
    }
}

使用

  • 增加快取
/**
     * 礦場屬性快取
     *
     * @param farmCode     礦場編號
     * @param farmProTable FarmProTable
     * @return
     */
    @CachePut(value = "farmProCache", key = "#farmCode")
    public FarmProTable addFarmPro(String farmCode, FarmProTable farmProTable) {

        if (StrUtil.isEmpty(farmCode)) {
            return farmProTable;
        }

        logger.info("{} addFarmPro 快取完成:{}", farmCode, new Date());

        return farmProTable;
    }
  • 刪除快取
/**
     * 礦場屬性快取
     *
     * @param farmCode
     * @return
     */
    @CacheEvict(value = "farmProCache", key = "#farmCode")
    public FarmProTable getFarmProFromCache(String farmCode) {

    }
  • 獲取快取
/**
     * 屬性快取
     *
     * @param farmCode
     * @return
     */
    @Cacheable(value = "farmProCache", key = "#farmCode")
    public FarmProTable getFarmProFromCache(String farmCode) {

        FarmProTable farmProTable = new FarmProTable();

        if (StrUtil.isEmpty(farmCode)) {
            return farmProTable;
        }

        //根據編號查詢屬性
        farmProTable = farmProTableRepository.findByFarmCode(farmCode);

        return farmProTable;
    }

待完善

  • 上面程式碼只是獲取快取資料,最好在上面再封裝一層,用於快取問題處理,比如處理快取穿透,雪崩等