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; }
待完善
- 上面代码只是获取缓存数据,最好在上面再封装一层,用于缓存问题处理,比如处理缓存穿透,雪崩等