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

待完善

  • 上面代码只是获取缓存数据,最好在上面再封装一层,用于缓存问题处理,比如处理缓存穿透,雪崩等
posted @ 2022-05-24 18:19  话·醉月  阅读(343)  评论(0编辑  收藏  举报