• (转)使用 Spring缓存抽象 支持 EhCache 和 Redis 混合部署


    背景:最近项目组在开发本地缓存,其中用到了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>

    参考链接:http://blog.csdn.net/pmlpml/article/details/53116377

  • 相关阅读:
    jdk版本切换
    Java开发中遇到的问题
    递归删除文件夹
    重写equals方法
    JSP基础
    js把变量转换成json数据
    myBatista批量查询和插入
    Jquery密码强度校验
    Linux配置外网访问mysql
    linux下开启、关闭、重启mysql服务命令
  • 原文地址:https://www.cnblogs.com/lixuwu/p/8427029.html
Copyright © 2020-2023  润新知