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

 

posted @ 2019-06-03 14:38  蔡徐坤1987  阅读(192)  评论(0编辑  收藏  举报