赞
踩
package com.hc.config.redis; import com.fasterxml.jackson.annotation.JsonAutoDetect; 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.datatype.jsr310.JavaTimeModule; import org.springframework.cache.annotation.EnableCaching; 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.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 @Configuration public class RedisConfig { /** * 过期时间1天 */ private final Duration timeToLive = Duration.ofDays(1); private final StringRedisSerializer keySerializer = new StringRedisSerializer(); /** * 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) */ private final Jackson2JsonRedisSerializer valueSerializer = new Jackson2JsonRedisSerializer(Object.class); /** * 代码块,会优先执行 * 用来设置Jackson2JsonRedisSerializer */ { ObjectMapper objectMapper = new ObjectMapper(); //设置所有访问权限以及所有的实际类型都可序列化和反序列化 objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 指定序列化输入的类型,类必须是非final修饰的 objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); //下面两行解决Java8新日期API序列化问题 objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.registerModule(new JavaTimeModule()); valueSerializer.setObjectMapper(objectMapper); } /** * 在SpringBoot2.0之后,spring容器自动的生成了StringRedisTemplate和RedisTemplate<Object,Object>,可以直接注入 * 但是在实际使用中,大多不会直接使用RedisTemplate<Object,Object>,而是会对key,value进行序列化,所以我们还需要新增一个配置类 * 换句话说,由于原生的redis自动装配,在存储key和value时,没有设置序列化方式,故自己创建redisTemplate实例 * * @param factory * @return */ @Bean(name = "redisTemplate") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // key采用String的序列化方式 template.setKeySerializer(keySerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(keySerializer); // value序列化方式采用jackson template.setValueSerializer(valueSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(valueSerializer); template.afterPropertiesSet(); return template; } @Bean(name = "cacheManager") public RedisCacheManager cacheManager(RedisConnectionFactory factory) { // 配置序列化(解决乱码的问题),通过config对象对缓存进行自定义配置 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() // 设置缓存的默认过期时间 .entryTtl(timeToLive) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer)) // 不缓存空值 .disableCachingNullValues(); //缓存配置 Map<String, RedisCacheConfiguration> cacheConfig = new HashMap<>(); //自定义缓存名,后面使用的@Cacheable的CacheName //缓存所有类别 cacheConfig.put("productCategory", config); //缓存所有省 cacheConfig.put("province", config); //缓存所有市 cacheConfig.put("city", config); //缓存所有乡镇 cacheConfig.put("country", config); //根据redis缓存配置和reid连接工厂生成redis缓存管理器 RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .transactionAware() .withInitialCacheConfigurations(cacheConfig) .build(); return redisCacheManager; } }
package com.hc.config.redis; import com.hc.constant.GlobalConstant; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import java.lang.reflect.Field; @Component public class RedisCityConfig { /** * 缓存键自动生成器 * * @return */ @Bean(name = "cityKeyGen") public KeyGenerator keyGenerator() { //设置自定义key{ClassName + methodName + params} return (target, method, params) -> { StringBuilder sb = new StringBuilder(); sb.append(GlobalConstant.redis.CITY_LIST); sb.append("("); for (int i = 0; i < params.length; i++) { sb.append(params[i].toString()); if (i != (params.length - 1)) { sb.append(","); } } sb.append(")"); return sb.toString(); }; } /** * 自定义keyGenerator,Key生成器 * * @return */ @Bean(name = "cityUpdateByIdKeyGen") public KeyGenerator updateByIdkeyGenerator() { return (target, method, params) -> { StringBuilder sb = new StringBuilder(); sb.append(GlobalConstant.redis.CITY_LIST); sb.append("("); try { Field id = params[0].getClass().getDeclaredField("id"); id.setAccessible(true); sb.append(id.get(params[0]).toString()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } sb.append(")"); return sb.toString(); }; } /** * 自定义keyGenerator,Key生成器 * * @return */ @Bean(name = "cityDeleteByIdKeyGen") public KeyGenerator deleteByIdkeyGenerator() { return (target, method, params) -> { StringBuilder sb = new StringBuilder(); sb.append(GlobalConstant.redis.CITY_LIST); sb.append("("); for (int i = 0; i < params.length; i++) { sb.append(params[i].toString()); if (i != (params.length - 1)) { sb.append(","); } } sb.append(")"); return sb.toString(); }; } }
package com.hc.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.hc.domain.City; import com.hc.mapper.CityMapper; import com.hc.service.CityService; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.List; /** * @author hecai */ @Service @CacheConfig(cacheManager = "cacheManager", cacheNames = "city") public class CityServiceImpl extends ServiceImpl<CityMapper, City> implements CityService { @Override public int updateBatchSelective(List<City> list) { return baseMapper.updateBatchSelective(list); } @Override public int batchInsert(List<City> list) { return baseMapper.batchInsert(list); } @Override @Cacheable(keyGenerator = "cityKeyGen") public List<City> findAllByProvinceId(Integer id) { QueryWrapper<City> queryWrapper = new QueryWrapper(); queryWrapper.eq("province_id", id); return baseMapper.selectList(queryWrapper); } }
注意:keyGenerator = “cityKeyGen” 会去先执行 RedisCityConfig里面的对应的方法,回去redis里面找到对应的key看是否存在,不存在才会去数据库查。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。