背景:最近项目组在开发本地缓存,其中用到了redis和ehcache,但是在使用注解过程中发现两者会出现冲突,这里给出解决两者冲突的具体方案。
spring-ehcache.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:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd"> <description>ehcache缓存配置管理文件</description> <bean id="ehCacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:ehcache/ehcache.xml" /> </bean> <bean id="ehCacheCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehCacheManagerFactory" /> </bean> </beans>
整合Ehcache和Redis的cacheManager,并注入容器:
package org.szfs.basic.middle.cache; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; /** * 缓存集成配置类<p> * * 该类通过向spring提供统一的{@link CacheManager}以达到集成不同缓存中间件的目的,v0.1包括redis与ehcache<br> * 该类重写了{@link CachingConfigurerSupport#cacheManager()}和{@link CachingConfigurerSupport#keyGenerator()}的方法 * * @author 51 * @version $Id: SzfsCacheConfig.java, v 0.1 2018年2月5日 下午6:45:44 51 Exp $ * * @see org.springframework.cache.annotation.CachingConfigurerSupport */ @Configuration @EnableCaching public class SzfsCacheConfig extends CachingConfigurerSupport { /** * redis缓存前缀<p> * 用于通过缓存名前缀识别缓存中间件 */ private static final String REDIS_PREFIX = "redis-"; @Autowired(required = false) private volatile RedisCacheManager redisCacheManager; @Autowired(required = false) private volatile EhCacheCacheManager ehCacheCacheManager; public SzfsCacheConfig() { super(); } /** * 构建CacheManager的实例szfsCacheManager<p> * * szfsCacheManager通过缓存名称<b>前缀</b>来识别缓存类型: * <ul> * <li>"redis-": redis cache</li> * <li> others : ehcache cache</li> * </ul> * 该实例是spring操作缓存所必须的,且需要保证唯一,这意味着,如果还需要Spring集成其它缓存中间件,仍然需要集成到szfsCacheManager<br> * * @see org.springframework.cache.annotation.CachingConfigurerSupport#cacheManager() */ @Bean("szfsCacheManager") @Override public CacheManager cacheManager() { return new CacheManager() { @Override public Collection<String> getCacheNames() { Collection<String> cacheNames = new ArrayList<String>(); if (redisCacheManager != null) { cacheNames.addAll(redisCacheManager.getCacheNames()); } if (ehCacheCacheManager != null) { cacheNames.addAll(ehCacheCacheManager.getCacheNames()); } return cacheNames; } @Override public Cache getCache(String name) { if (name.startsWith(REDIS_PREFIX)) { return redisCacheManager == null ? null : redisCacheManager.getCache(name); } else { return ehCacheCacheManager == null ? null : ehCacheCacheManager.getCache(name); } } }; } /** * 构建默认的键生成器 * @see org.springframework.cache.annotation.CachingConfigurerSupport#keyGenerator() */ @Bean @Override public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuilder keyStrBuilder = new StringBuilder(); keyStrBuilder.append(target.getClass().getName()); keyStrBuilder.append(method.getName()); for (Object _param : params) { keyStrBuilder.append(_param.toString()); } return keyStrBuilder.toString(); } }; } public RedisCacheManager getRedisCacheManager() { return redisCacheManager; } public void setRedisCacheManager(RedisCacheManager redisCacheManager) { this.redisCacheManager = redisCacheManager; } public EhCacheCacheManager getEhCacheCacheManager() { return ehCacheCacheManager; } public void setEhCacheCacheManager(EhCacheCacheManager ehCacheCacheManager) { this.ehCacheCacheManager = ehCacheCacheManager; } }
redis相关配置:
<?xml version="1.0" encoding="UTF-8"?> <!-- Spring集成redis sentinel配置,对应配置文件:redis-sentinel.properties --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <description>Spring集成redis岗哨配置</description> <!--配置 jedis pool --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="${redis.sentinel.jedis.pool.maxTotal}" /> <property name="maxIdle" value="${redis.sentinel.jedis.pool.maxIdle}" /> <property name="minIdle" value="${redis.sentinel.jedis.pool.minIdle}" /> <property name="numTestsPerEvictionRun" value="${redis.sentinel.jedis.pool.numTestsPerEvictionRun}" /> <property name="timeBetweenEvictionRunsMillis" value="${redis.sentinel.jedis.pool.timeBetweenEvictionRunsMillis}" /> <property name="minEvictableIdleTimeMillis" value="${redis.sentinel.jedis.pool.minEvictableIdleTimeMillis}" /> <property name="softMinEvictableIdleTimeMillis" value="${redis.sentinel.jedis.pool.softMinEvictableIdleTimeMillis}" /> <property name="maxWaitMillis" value="${redis.sentinel.jedis.pool.maxWaitMillis}" /> <property name="testOnBorrow" value="${redis.sentinel.jedis.pool.testOnBorrow}" /> <property name="testWhileIdle" value="${redis.sentinel.jedis.pool.testWhileIdle}" /> <property name="blockWhenExhausted" value="${redis.sentinel.jedis.pool.blockWhenExhausted}" /> </bean> <!-- 配置redisSentinelConfiguration --> <bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> <property name="master"> <bean class="org.springframework.data.redis.connection.RedisNode"> <property name="name" value="mymaster" /> </bean> </property> <property name="sentinels"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel.node1.host}" /> <constructor-arg name="port" value="${redis.sentinel.node1.port}" /> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel.node2.host}" /> <constructor-arg name="port" value="${redis.sentinel.node2.port}" /> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel.node3.host}" /> <constructor-arg name="port" value="${redis.sentinel.node3.port}" /> </bean> </set> </property> </bean> <!-- 配置JedisConnectionFactory --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="password" value="${redis.sentinel.password}" /> <constructor-arg ref="jedisPoolConfig" /> <constructor-arg ref="redisSentinelConfiguration" /> </bean> <!-- 配置redisTemplate --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> <!-- 支持事务 --> <property name="enableTransactionSupport" value="true" /> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" /> </property> </bean> <!-- 配置redisCacheManager --> <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg name="redisOperations" ref="redisTemplate" /> <!-- 默认有效期,单位:秒 --> <property name="defaultExpiration" value="3600" /> <!-- 多个缓存有效期,单位:秒 --> <property name="expires"> <map> <entry key="redis-users" value="10" /> </map> </property> </bean> <!-- 配置RedisLockRegistry --> <bean id="redisLockRegistry" class="org.springframework.integration.redis.util.RedisLockRegistry"> <constructor-arg type="org.springframework.data.redis.connection.RedisConnectionFactory" ref="jedisConnectionFactory" /> <constructor-arg type="java.lang.String" value="${redis.sentinel.registry.key}" /> </bean> </beans>