spring整合redis
web.xml
<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:conf/app-context.xml </param-value> </context-param>
app-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <import resource="app-cache.xml" /> </beans>
app-cache.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- Cache的Redis Template --> <bean id="cacheRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="cacheRedisConnectionFactory" /> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> </bean> <!-- 配置缓存 --> <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManagerEx"> <constructor-arg ref="cacheRedisTemplate" /> <!-- 默认Key有效期24小时(3600*24) --> <property name="defaultExpiration" value="3600" /> <property name="usePrefix" value="true" /> <property name="expires"> <map> <!-- Database Keys --> <entry key="CACHE:CBM_MAG:COMPANY" value="600" /> <entry key="CACHE:CBM_MAG:PRODUCT" value="600" /> <entry key="CACHE:CBM_COMMON:DATA_DICT_CONTENT" value="600" /> <entry key="CACHE:BUSINESS:CAR_TYPE" value="600" /> <entry key="CACHE:BUSINESS:CAR_TYPE" value="600" /> <entry key="CACHE:BUSINESS:DEVICE_SUMMARY" value="900" /> <entry key="CACHE:CLOUD:ALARM_REALTIME" value="180" /> <entry key="CACHE:CLOUD:ALARM_SUMMARY_REALTIME" value="3600" /> <entry key="CACHE:CLOUD:ALARM_SUMMARY" value="3600" /> <entry key="CACHE:CLOUD:ALARM_DAILY" value="3600" /> <entry key="CACHE:CLOUD:ALARM_MONTHLY" value="3600" /> <entry key="CACHE:CLOUD:DEVICE_DAILY" value="3600" /> <entry key="CACHE:CLOUD:DEVICE_MONTHLY" value="3600" /> <entry key="CACHE:CLOUD:DEVICE_STATS" value="3600" /> <entry key="CACHE:CLOUD:CAPACITY_DAILY" value="3600" /> <entry key="CACHE:CLOUD:CAPACITY_MONTHLY" value="3600" /> <entry key="CACHE:CLOUD:WORK_DURATION_DAILY" value="3600" /> <entry key="CACHE:CLOUD:WORK_DURATION_MONTHLY" value="3600" />
。。。。。
</map>
</property>
</bean> <!-- Key生成策略配置 --> <bean id="defaultKeyGenerator" class="com.foton.m2m.basic.core.cache.DefaultKeyGenerator" />
<!-- 开启spring缓存注解 --> <cache:annotation-driven cache-manager="cacheManager" key-generator="defaultKeyGenerator" /> </beans>
/**
* 实现spring cache的默认缓存实现策略
*
* @author gaolixiang2 2017年6月20日
*/
public class DefaultKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return new DefaultKey(target, method, params).getString();
}
}
public class DefaultKey implements Serializable {
private static final long serialVersionUID = 1930236297081366076L;
/** 调用目标对象全类名 */
private String targetClassName;
/** 调用目标方法名称 */
private String methodName;
/** 调用目标参数 */
private Object[] params;
private final int hashCode;
public DefaultKey(Object target, Method method, Object[] elements) {
this.targetClassName = target.getClass().getName();
this.methodName = generatorMethodName(method);
if (ArrayUtils.isNotEmpty(elements)) {
this.params = new Object[elements.length];
for (int i = 0; i < elements.length; i++) {
Object ele = elements[i];
if (ele instanceof Persistable) {
try {
Map<String, ? extends Object> properties = BeanUtils.describe(ele);
this.params[i] = properties;
} catch (Exception e) {
this.params[i] = ele;
}
} else if (ele instanceof Class) {
this.params[i] = ((Class) ele).getName();
} else {
this.params[i] = ele;
}
}
}
this.hashCode = generatorHashCode();
}
public String getString() {
return targetClassName + ":" + methodName + ":" + hashCode;
}
private String generatorMethodName(Method method) {
StringBuilder builder = new StringBuilder();
Class<?>[] types = method.getParameterTypes();
if (ArrayUtils.isNotEmpty(types)) {
builder.append("(");
for (Class<?> type : types) {
String name = type.getName();
builder.append(name + ",");
}
builder.append(")");
}
return method.getName() + builder.toString().hashCode();
}
// 生成hashCode
private int generatorHashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((methodName == null) ? 0 : methodName.hashCode());
result = prime * result + hashCode(params);
result = prime * result + ((targetClassName == null) ? 0 : targetClassName.hashCode());
return result;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (int i = 0; i < a.length; i++) {
Object element = a[i];
if (element == null) {
result = 31 * result + (i + "null").hashCode();
} else if (element instanceof Collection) {
Collection<?> collection = (Collection) element;
int j = 0;
for (Object subElement : collection) {
result = 31 * result + (subElement == null ? (j + "snull").hashCode() : subElement.hashCode());
j++;
}
} else if (element.getClass().isArray()) {
Object[] subElement = (Object[]) element;
for (int j = 0; j < subElement.length; j++) {
result = 31 * result + (subElement == null ? (j + "snull").hashCode() : subElement.hashCode());
}
} else if (element instanceof Map) {
Map map = (Map) element;
Set<Map.Entry> entrySet = map.entrySet();
int j = 0;
for (Map.Entry<?, ?> subElement : entrySet) {
result = 31 * result + (subElement == null ? (j + "snull").hashCode() : subElement.hashCode());
j++;
}
} else {
result = 31 * result + element.hashCode();
}
}
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DefaultKey other = (DefaultKey) obj;
if (hashCode != other.hashCode)
return false;
if (methodName == null) {
if (other.methodName != null)
return false;
} else if (!methodName.equals(other.methodName))
return false;
if (!Arrays.equals(params, other.params))
return false;
if (targetClassName == null) {
if (other.targetClassName != null)
return false;
} else if (!targetClassName.equals(other.targetClassName))
return false;
return true;
}
@Override
public final int hashCode() {
return hashCode;
}
调用:
@Cacheable(value = Constants.BUSINESS_CACHE_NAME_PREFIX + "SERVICER", unless = "#result.size() eq 0")
public List<Map<String, Object>> findMapGroupByProvince(Long companyId, Long productId, Long brandId) {
...
}
说明:Spring cache key 生成策略 类名+方法名+参数信息
补充:关于生成策略多种多样,foton使用的策略是类路径hashcode + 方法hashcode + 参数hashcode 这样存储命中率比较低节约空间
DefaultKey.java
浙公网安备 33010602011771号