不多说开干
1.pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.7</version>
</dependency>
2.启动类上面加上@EnableCaching 开启缓存注解
/**
* @author lime
*/
@EnableCaching
@SpringBootApplication
@MapperScan("com.lc.clcs.mapper")
public class ClcsWxApplication {
public static void main(String[] args) {
SpringApplication.run(ClcsWxApplication.class, args);
}
}
3.application-prod.yml在springboot配置文件配置redis
#redis
redis:
database: 0
host: 36.103.240.26
port: 6379
password:
jedis:
pool:
max-active: 8
max-idle: 8
min-idle: 0
4.redis缓存配置 RedisCacheConfig.java
*******
/**
* @author lime
* redis 缓存配置
*/
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheConfig {
/**
* 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
*
* @return
*/
@Bean
public RedisSerializer<Object> jackson2JsonRedisSerializer() {
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
return serializer;
}
/**
* 配置自定义redisTemplate
*
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setValueSerializer(jackson2JsonRedisSerializer());
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* 设置redis缓存过期时间
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory), this.getRedisCacheConfigurationWithTtl(60), this.getRedisCacheConfigurationMap());
}
/**
* 自定义设置缓存时间
* WechatCacheNames 微信缓存名称常量类
*
* @return
*/
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(10);
//设置微信api授权token失效时间为2小时
redisCacheConfigurationMap.put(WechatCacheNames.WECHAT_API_ACCESS_TOKEN_CACHE, this.getRedisCacheConfigurationWithTtl(60 * 60 * 2));
//设置微信公众号菜单失效时间
redisCacheConfigurationMap.put(WechatCacheNames.WECHAT_NO_PUBLIC_MENU_CACHE, this.getRedisCacheConfigurationWithTtl(60 * 99999));
return redisCacheConfigurationMap;
}
/**
*
* @param seconds 秒
* @return
*/
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer)
).entryTtl(Duration.ofSeconds(seconds));
return redisCacheConfiguration;
}
}
5.缓存key生成策略
package com.lc.clcs.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
/**
* @author lime
* 配置缓存key的生成
* key : WechatMenuButtonCache::com.lc.clcs.service.impl.WechatServiceImpl_getMenu_
*/
@Configuration
public class CachingConfig extends CachingConfigurerSupport {
@Bean
@Override
public KeyGenerator keyGenerator() {
return (Object target, Method method, Object... params) -> {
StringBuilder sb = new StringBuilder(16);
sb.append(target.getClass().getName());
sb.append("_");
sb.append(method.getName());
sb.append("_");
for (int i = 0, len = params.length; i < len; i++) {
sb.append(params[i]);
if (i < len - 1) {
sb.append(",");
}
}
return sb.toString();
};
}
}
@Cacheable(cacheNames = WechatCacheNames.WECHAT_API_ACCESS_TOKEN_CACHE)
@Override
public AccessToken getAccessToken() {
return WechatTools.getAccessToken();
}
注意事项:
1.如果遇到缓存没有生效
检查是否在同一个类中调用了其他缓存方法,注解使用是不能再同一个类中调用当前类的其他缓存方法
@Cacheable(cacheNames = WechatCacheNames.WECHAT_API_ACCESS_TOKEN_CACHE)
@Override
public AccessToken getAccessToken() {
return WechatTools.getAccessToken();
}
@Cacheable(cacheNames = WechatCacheNames.WECHAT_API_ACCESS_TOKEN_CACHE)
public AccessToken getToken() {
//错误调用 缓存没有生效
return getAccessToken();
}
2.业务类接口 及接口实现,缓存注解只作用于实现了接口的方法,方法是public,私有方法等缓存不生效
3.Caused by: io.lettuce.core.RedisCommandExecutionException: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error. 引起:io.lettuce.core.RedisCommandExecutionException:MISCONF Redis配置为保存RDB快照,但它目前无法在磁盘上保留。 可以修改数据集的命令被禁用,因为如果RDB快照失败(stop-writes-on-bgsave-error选项),此实例配置为在写入期间报告错误。 有关RDB错误的详细信息,请查看Redis日志。
解决方案:在redis-cli执行
config set stop-writes-on-bgsave-error no