SpringBoot------自定义Redis缓存Cache
SpringBoot自带Cache存在问题:
1.生成Key过于简单,容易冲突 默认为cacheNames + “:” + Key
2.无法设置过期时间,默认时间是永久
3.配置序列化方式,默认是JDKSerializable,可能造成乱码
自定义Cache分三个步骤:
1.自定义KeyGenerator
2.自定义cacheManager 设置缓存过期时间
3.自定义序列化方式 JackSon
1.修改pom.xml文件
<!-- redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
<!-- cache --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
2.添加RedisConfig.java配置
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cache.CacheManager; 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.cache.RedisCacheWriter; 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.StringRedisSerializer; import java.time.Duration; import java.util.HashMap; import java.util.Map; /** * @EnableCaching 开启SpringBoot的Cache缓存 * * */ @Configuration @EnableCaching public class RedisConfig { @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){ RedisTemplate<String, String> template = new RedisTemplate<>(); template.setConnectionFactory(factory); return template; } /** * 自定义key值格式 * * */ @Bean public KeyGenerator simpleKeyGenerator(){ return (o, method, objects) -> { StringBuilder builder = new StringBuilder(); //获取类名称 builder.append(o.getClass().getSimpleName()); builder.append("."); //获取方法名称 builder.append(method.getName()); builder.append("["); //遍历方法参数 for (Object obj : objects){ builder.append(obj.toString()); } builder.append("]"); return builder.toString(); }; } @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){ return new RedisCacheManager( RedisCacheWriter.lockingRedisCacheWriter(redisConnectionFactory), //默认Cache缓存的超时配置 this.getRedisCacheConfigurationWithTtl(30), //自定义Cache缓存Key的超时配置 this.getRedisCacheConfigurationMap() ); } /** * 配置自定义Cache缓存Key的超时规则 * * */ public Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap(){ Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(); redisCacheConfigurationMap.put("UserInfoCacheList", this.getRedisCacheConfigurationWithTtl(20)); // redisCacheConfigurationMap.put("UserInfoCacheAnother", this.getRedisCacheConfigurationWithTtl(30)); return redisCacheConfigurationMap; } /** * 自定义Cache缓存超时规则 * * */ public RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds){ Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(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(); //修改Key的命名规则 默认:cacheName + ":" // .computePrefixWith(cacheName -> cacheName.concat(":")) // .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())); redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith( RedisSerializationContext .SerializationPair .fromSerializer(jackson2JsonRedisSerializer) ).entryTtl(Duration.ofSeconds(seconds)); return redisCacheConfiguration; } }
3.添加Service配置
备注:
只有最后一个是自定义的 前面的是springboot自带的方法
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.theng.shopuser.entity.UserInfo; import com.theng.shopuser.entity.dto.UserInfoDto; import com.theng.shopuser.mapper.UserInfoMapper; import com.theng.shopuser.service.UserInfoService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import java.io.Serializable; import java.util.List; /** * <p> * 服务实现类 * </p> * * @author tianheng * @since 2020-02-09 */ @Service @CacheConfig(cacheNames = "userInfoCache") public class UserInfoService { @Autowired private UserInfoMapper userInfoMapper;/** * 获取缓存中的UserInfo * #p0: 对应方法参数 0表示第一个参数 * * */ @Override @Nullable @Cacheable(key = "#p0", unless = "#result == null") public UserInfo findUserInfoCache(String code){ return userInfoMapper.findUserInfoByCode(code); } /** * 向缓存中插入UserInfo * return: 必须要有返回值 否则无法保存到缓存中 * * */ @Override @CachePut(key = "#p0.userCode") public UserInfo insertUserInfoCache(UserInfo userInfo){ return null; } /** * 向缓存中插入UserInfo * return: 必须要有返回值 否则无法保存到缓存中 * * */ @Override @CachePut(key = "#p0.userCode") public UserInfo updateUserInfoCache(UserInfo userInfo){ return null; } /** * 删除cacheNames = "userInfoCache",key值为指定值的缓存 * * */ @Override @CacheEvict(key = "#p0") public void deleteUserInfoCache(String userCode){ } /** * 清除cacheNames = "userInfoCache"下的所有缓存 * 如果失败了,则不会清除 * * */ @Override @CacheEvict(allEntries = true) public void deleteAllUserInfoCache(){ } @Nullable @Cacheable(value = "UserInfoCacheList", keyGenerator = "simpleKeyGenerator") public UserInfo customUserInfoCache(){ return null; } }
4.修改controller.java
import com.theng.shopuser.bean.UserSessionBean; import com.theng.shopuser.entity.UserInfo; import com.theng.shopuser.service.UserInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.*; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/user-info") public class UserInfoController { @Autowired private UserInfoService userInfoService; //测试 @GetMapping("/list2") public Object getList2() { UserInfo userInfo = userInfoService.findUserInfoByCode("YH006"); return "success"; } @GetMapping("/list3") public Object getList3() {
UserInfo userInfo = userInfoService.customUserInfoCache();
return "success"; } }
5.修改pom.xml文件
spring: redis: database: 0 host: localhost port: 6379 password:
6.输出结果
自定义