- key生成核心逻辑
package com.kiiik.config.redis.cache; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.util.CollectionUtils; /** *作者 : iechenyb<br> *类描述: 说点啥<br> *创建时间: 2018年11月20日 * "userInfor#1800#90"; */ public class BaseCacheKey { public final static String CACHE_SPLIT = "#"; Log log = LogFactory.getLog(BaseCacheKey.class); private final Object[] params; private final int hashCode; private final String className; private final String methodName; private final String simpleName; private String baseKey=null;//kiiik.zuul.baseKey.*** public BaseCacheKey(Object target, Method method, Object[] elements) throws Exception{ this.className=target.getClass().getName(); this.simpleName=target.getClass().getSimpleName(); this.methodName=getMethodName(method); this.params = new Object[elements.length]; System.arraycopy(elements, 0, this.params, 0, elements.length); this.hashCode=generatorHashCode(); initKey(method); } public BaseCacheKey(Object target, Method method) throws Exception{ this.className=target.getClass().getName(); this.simpleName=target.getClass().getSimpleName(); this.methodName=getMethodName(method); this.params = null; StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); this.hashCode= sb.toString().hashCode(); initKey(method); } //key#timeout#refresh public String initKey(Method method) throws Exception{ List<String> keys = new ArrayList<>(); if(method.isAnnotationPresent(Cacheable.class)){ Cacheable a = method.getAnnotation(Cacheable.class); if(!ArrayUtils.isEmpty(a.cacheNames())){ keys = Arrays.asList(a.cacheNames()); }else{ keys = Arrays.asList(a.value()); } }else if(method.isAnnotationPresent(CachePut.class)){ CachePut a = method.getAnnotation(CachePut.class); if(!ArrayUtils.isEmpty(a.cacheNames())){ keys = Arrays.asList(a.cacheNames()); }else{ keys = Arrays.asList(a.value()); } }else if(method.isAnnotationPresent(CacheEvict.class)){ CacheEvict a = method.getAnnotation(CacheEvict.class); if(!ArrayUtils.isEmpty(a.cacheNames())){ keys = Arrays.asList(a.cacheNames()); }else{ keys = Arrays.asList(a.value()); } }else{ throw new Exception("缓存key的value或者names格式不正确。格式=唯一名称#过期时间#刷新时间"); } if(!CollectionUtils.isEmpty(keys)){ baseKey = keys.get(0).split(CACHE_SPLIT)[0]; }else{ baseKey=null; } return baseKey; } private String getMethodName(Method method){ StringBuilder builder = new StringBuilder(method.getName()); Class<?>[] types = method.getParameterTypes(); if(types.length!=0){ builder.append("("); for(Class<?> type:types){ String name = type.getName(); builder.append(name+","); } builder.append(")"); } return builder.toString(); } @Override public boolean equals(Object obj){ if(this==obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; BaseCacheKey o=(BaseCacheKey) obj; if(this.hashCode!=o.hashCode()) return false; if (!Arrays.equals(params, o.params)) return false; return true; } @Override public final int hashCode() { return hashCode; } /** * *作者 : iechenyb<br> *方法描述: 参数为空时,每个对象都一样<br> *创建时间: 2018年11月22日 *@return */ private int generatorHashCode() { final int prime = 31; int result = 1; result = prime * result + hashCode; result = prime * result + ((className == null) ? 0 : className.hashCode()); result = prime * result + ((methodName == null) ? 0 : methodName.hashCode()); if(params.length>0){ result = prime * result + Arrays.deepHashCode(params);//没有考虑对象的情况,需要对每个对象参数进行重写hashcode方法 } return result; } /** * 类名+方法名+name|value+hashcode */ @Override public String toString() { /*return "BaseCacheKey [params=" + Arrays.deepToString(params) + ", className=" + className + ", methodName=" + methodName + "]";*/ return RedisUtils.keyBuilder(simpleName, baseKey, String.valueOf(hashCode)); } }
- 定制redis缓存
package com.kiiik.config.redis.cache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.data.redis.cache.RedisCache; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.core.RedisOperations; import org.springframework.util.Assert; /** * 作者 : iechenyb<br> * 类描述: 说点啥<br> * 创建时间: 2018年11月21日 */ public class CustomizeRedisCacheManager extends RedisCacheManager { Log log = LogFactory.getLog(CustomizeRedisCacheManager.class); CustomizeRedisCacheManager(RedisOperations<?, ?> redisOperations) { super(redisOperations); } @SuppressWarnings("unchecked") @Override protected RedisCache createCache(String cacheName) { Assert.hasText(cacheName, "CacheName must not be null or empty!"); String[] values = cacheName.split("#"); long expiration = computeExpiration(values); return new RedisCache(values[0], (isUsePrefix() ? getCachePrefix().prefix(cacheName) : null), getRedisOperations(), expiration, false); } private long computeExpiration(String[] values) { if (values.length > 1) { return Long.parseLong(values[1]); } // 如果说想使用默认的过期时间而不指定特殊时间,则可以直接@Cacheable(cacheNames="name"),不需要加'#过期时间'了 return super.computeExpiration(values[0]); } }
- 定制key生成器
package com.kiiik.config.redis.cache; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.stereotype.Component; /** * 作者 : iechenyb<br> * 类描述: 说点啥<br> * 创建时间: 2018年11月20日 */ @Component("cacheKeyGenerator") // 开启缓存 @EnableCaching public class BaseCacheKeyGenerator implements KeyGenerator { Log log = LogFactory.getLog(BaseCacheKeyGenerator.class); // private Duration timeToLive = Duration.ZERO; @Override public Object generate(Object target, Method method, Object... params) { try { return new BaseCacheKey(target, method, params).toString(); } catch (Exception e) { e.printStackTrace(); return null; } } /* * 默认的处理方式 * * @Bean public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) * { * * redisTemplate.setKeySerializer(keySerializer()); * redisTemplate.setValueSerializer(valueSerializer()); * redisTemplate.setHashKeySerializer(keySerializer()); * redisTemplate.setHashValueSerializer(valueSerializer()); * * RedisCacheManager redisCacheManager= new * RedisCacheManager(redisTemplate); * redisCacheManager.setDefaultExpiration(3600); Map<String,Long> * expiresMap=new HashMap<>(); expiresMap.put("Product",5L); * redisCacheManager.setExpires(expiresMap); return redisCacheManager; } */ // 定制的处理方式 @Bean public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) { redisTemplate.setKeySerializer(stringKeySerializer()); redisTemplate.setValueSerializer(valueSerializer()); redisTemplate.setHashKeySerializer(stringKeySerializer()); redisTemplate.setHashValueSerializer(valueSerializer()); CustomizeRedisCacheManager redisCacheManager = new CustomizeRedisCacheManager(redisTemplate); redisCacheManager.setDefaultExpiration(3600); Map<String, Long> expiresMap = new HashMap<>(); expiresMap.put("Product", 5L); redisCacheManager.setExpires(expiresMap); return redisCacheManager; } @Bean(name = "redisTemplate") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setKeySerializer(stringKeySerializer()); redisTemplate.setHashKeySerializer(stringKeySerializer()); redisTemplate.setValueSerializer(valueSerializer()); redisTemplate.setHashValueSerializer(valueSerializer()); log.debug("自定义RedisTemplate加载完成"); return redisTemplate; } public JdkSerializationRedisSerializer jdkKeySerializer() { return new JdkSerializationRedisSerializer(); } public StringRedisSerializer stringKeySerializer() { return new StringRedisSerializer(); } private RedisSerializer<Object> valueSerializer() { return new GenericJackson2JsonRedisSerializer(); } }
- 辅助工具类
package com.kiiik.config.redis.cache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.StringUtils; import com.cyb.freemarker.mvc.base.BaseController; /** *作者 : iechenyb<br> *类描述: 说点啥<br> *创建时间: 2018年11月22日 */ public class RedisUtils { Log log = LogFactory.getLog(RedisUtils.class); /** * 主数据系统标识 */ public static final String KEY_PREFIX = "system:example"; /** * 分割字符,默认[:],使用:可用于rdm分组查看 */ private static final String KEY_SPLIT_CHAR = ":"; /** * redis的key键规则定义 * @param module 模块名称 * @param func 方法名称 * @param args 参数.. * @return key */ public static String keyBuilder(String module, String func, String... args) { return keyBuilder(null, module, func, args); } private static String keyName(String value) throws Exception{ if(StringUtils.isEmpty(value)){ throw new Exception("缓存没有定义对应的key名称"); } if(value.split("#").length > 0){ return value.split("#")[0]; } return value; } public static String keyBuilder(Class<?> clazz, String name) throws Exception { return new StringBuffer(KEY_PREFIX) .append(KEY_SPLIT_CHAR) .append(clazz.getSimpleName()) .append(KEY_SPLIT_CHAR) .append(keyName(name)) .toString(); } /** * redis的key键规则定义 * @param module 模块名称 * @param func 方法名称 * @param objStr 对象.toString() * @return key */ public static String keyBuilder(String module, String func, String objStr) { return keyBuilder(null, module, func, new String[]{objStr}); } /** * redis的key键规则定义 * @param prefix 项目前缀 * @param module 模块名称 * @param func 方法名称 * @param objStr 对象.toString() * @return key */ public static String keyBuilder(String prefix, String module, String func, String objStr) { return keyBuilder(prefix, module, func, new String[]{objStr}); } /** * redis的key键规则定义 * @param prefix 项目前缀 * @param module 模块名称 * @param func 方法名称 * @param args 参数.. * @return key */ public static String keyBuilder(String prefix, String module, String func, String... args) { // 项目前缀 if (prefix == null) { prefix = KEY_PREFIX; } StringBuilder key = new StringBuilder(prefix); // KEY_SPLIT_CHAR 为分割字符 key.append(KEY_SPLIT_CHAR).append(module).append(KEY_SPLIT_CHAR).append(func); for (String arg : args) { key.append(KEY_SPLIT_CHAR).append(arg); } return key.toString(); } /** * redis的key键规则定义 * @param redisEnum 枚举对象 * @param objStr 对象.toString() * @return key */ public static String keyBuilder(RedisEnum redisEnum, String objStr) { return keyBuilder(redisEnum.getKeyPrefix(), redisEnum.getModule(), redisEnum.getFunc(), objStr); } public static void main(String[] args) throws Exception { System.out.println(keyBuilder("com.cyb.test", "method", String.valueOf(111))); System.out.println(keyBuilder("com.cyb.test", "method:value", String.valueOf(111))); System.out.println(keyBuilder(BaseController.class, "aaa")); } } package com.kiiik.config.redis.cache; /** *作者 : iechenyb<br> *类描述: 说点啥<br> *创建时间: 2018年11月22日 */ public enum RedisEnum { /** * 数据字典Service - 根据字典类型查询字典数据 */ RedisEnum( RedisUtils.KEY_PREFIX, "", "", ""); /** * 系统标识 */ private String keyPrefix; /** * 模块名称 */ private String module; /** * 方法名称 */ private String func; /** * 描述 */ private String remark; RedisEnum(String keyPrefix, String module, String func, String remark) { this.keyPrefix = keyPrefix; this.module = module; this.func = func; this.remark = remark; } public String getKeyPrefix() { return keyPrefix; } public void setKeyPrefix(String keyPrefix) { this.keyPrefix = keyPrefix; } public String getModule() { return module; } public void setModule(String module) { this.module = module; } public String getFunc() { return func; } public void setFunc(String func) { this.func = func; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }
springboot定制redis缓存
最新推荐文章于 2023-05-05 16:35:56 发布