一、使用开源包(spring-data-redis

1、引入jar包

<dependency>
     <groupId>org.springframework.data</groupId>
     <artifactId>spring-data-redis</artifactId>
     <version>1.8.11.RELEASE</version>
 </dependency>

2、配置Spring xml文件

<!--  结合现在配置 -->

<bean name="redisTemplate"
class=" RedisTemplate">
       <property name="redisPool"
ref="redisPool"/>
        <property name="keySerializer"
ref="org.springframework.data.redis.serializer.StringRedisSerializer"></property>
       <property name="hashKeySerializer" ref="org.springframework.data.redis.serializer.StringRedisSerializer"></property>
</bean>

<bean name="cacheManager" class="com.config.ExtendedRedisCacheManager">
    <constructor-arg name="redisOperations" ref="redisTemplate"/>
    <constructor-arg name="cacheNames">
        <set>
            <value>default</value>
            <value>test1</value>
        </set>
    </constructor-arg>
    <!-- 默认缓存名字 -->
 <property name="defaultCacheName" value="default"/>
    <!-- 是否在容器启动时初始化 -->
 <property name="loadRemoteCachesOnStartup" value="true"/>
    <!-- 是否使用前缀 -->
 <property name="usePrefix" value="true"/>
    <!-- 前缀命名,仅当usePrefix为true时才生效
-->
 <property name="cachePrefix">
        <bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix">
            <constructor-arg name="delimiter" value=":"/>
        </bean>
    </property>
    <!-- 缓存名字和有效期的分隔符 -->
 <property name="separator" value="#"/>
    <!-- 默认有效期60 -->
 <property name="defaultExpiration" value="60"/>
</bean>

ps:redis配置继续用现有的

3、配置redis挂掉,直接访问数据库(redis挂掉,最好配置预警)

@Configuration
@EnableCaching
public class AppCacheConfigurer extends CachingConfigurerSupport {
    private Logger logger =
LoggerFactory.getLogger(AppCacheConfigurer.class);

public class AppCacheErrorHandler implements CacheErrorHandler {
        @Override
 public void handleCacheGetError(RuntimeException e,
Cache cache, Object o) {
            if (e instanceof JedisConnectionException || e instanceof RedisConnectionFailureException) {
                logger.warn("redis has lose connection:", e);
                return;
            }
            throw e;
        }

@Override
 public void handleCachePutError(RuntimeException e,
Cache cache, Object o, Object o1) {
            if (e instanceof JedisConnectionException || e instanceof RedisConnectionFailureException) {
                logger.warn("redis has lose connection:", e);
                return;
            }
            throw e;
        }

@Override
 public void handleCacheEvictError(RuntimeException
e, Cache cache, Object o) {
            throw e;
        }

@Override
 public void handleCacheClearError(RuntimeException
e, Cache cache) {
            throw e;
        }
    }

@Override
 public CacheErrorHandler errorHandler() {
        return new AppCacheErrorHandler();
    }
}

5、配置独立设置过期时间,重写RedisCacheManager

public class ExtendedRedisCacheManager extends RedisCacheManager {

private static final Logger logger =
Logger.getLogger(ExtendedRedisCacheManager.class);

private static final ScriptEngine scriptEngine = new
ScriptEngineManager().getEngineByName("JavaScript");

private static final Pattern pattern = Pattern.compile("[+\\-*/%]");

private String defaultCacheName;

private char separator = '#';

public ExtendedRedisCacheManager(RedisOperations
redisOperations) {
        this(redisOperations, Collections.<String>emptyList());
    }

public ExtendedRedisCacheManager(RedisOperations
redisOperations, Collection<String> cacheNames) {
        super(redisOperations, cacheNames);
    }

@Override
 public Cache getCache(String name) {
        // try to get cache by name
 RedisCache cache
= (RedisCache) super.getCache(name);
        if (cache != null) {
            return cache;
        }

// there's no cache which has given name
 // find separator in cache name
 int index =
name.lastIndexOf(getSeparator());
        if (index < 0) {
            return null;
        }

// split name by the separator
 String cacheName
= name.substring(0, index);
        if(StringUtils.isBlank(cacheName)){
            cacheName = defaultCacheName;
        }
        cache = (RedisCache) super.getCache(cacheName);
        if (cache == null) {
            return null;
        }

// get expiration from name
 Long expiration
= getExpiration(name, index);
        if (expiration == null || expiration < 0) {
            logger.warn("Default expiration time will be used
for cache '{}' because cannot parse '{}', cacheName : " + cacheName + ", name : " + name);
            return cache;
        }

return new RedisCache(cacheName, (isUsePrefix() ?
getCachePrefix().prefix(cacheName) : null), getRedisOperations(), expiration);
    }

public char getSeparator() {
        return separator;
    }

/**
 * Char that separates cache name and
expiration time, default: #.
 *
 * @param separator
 */
 public void setSeparator(char separator) {
        this.separator = separator;
    }

private Long getExpiration(final String name, final int separatorIndex) {
        Long expiration = null;
        String expirationAsString =
name.substring(separatorIndex + 1);
        try {
            // calculate expiration, support arithmetic
expressions.
 if(pattern.matcher(expirationAsString).find()){
                expiration = (long) Double.parseDouble(scriptEngine.eval(expirationAsString).toString());
            }else{
                expiration =
Long.parseLong(expirationAsString);
            }
        } catch (NumberFormatException ex) {
            logger.error(String.format("Cannnot separate expiration time
from cache: '%s'",
name), ex);
        } catch (ScriptException e) {
            logger.error(String.format("Cannnot separate expiration time
from cache: '%s'",
name), e);
        }

return expiration;
    }

@Override
 public void setUsePrefix(boolean usePrefix) {
        super.setUsePrefix(usePrefix);
    }

@Override
 public void setCachePrefix(RedisCachePrefix
cachePrefix) {
        super.setCachePrefix(cachePrefix);
    }

public void setDefaultCacheName(String
defaultCacheName) {
        this.defaultCacheName
= defaultCacheName;
    }
}

6、通过注解设置缓存

@Cacheable(value = "test1#60",key = "#p0")//Cacheable会判断key是否存在,增加redis缓存,设置为60秒,key为test1:xxx

@CachePut(cacheNames="test1#60",key
= "#p0")//CachePut不会判断key是否存在,直接覆盖,增加redis缓存,设置为60秒,key为test1:xxx,它每次都会触发真实方法的调用

@CacheEvict(value = "test1",key = "#p1")//删除缓存

其他缓存注解,参考spring cache注解相关定义

二、解决现有系统版本不兼容问题

1、线上spring版本为:3.2.9.RELEASE

解决兼容redis挂掉的spring版本为4.1以上

适用于现在系统的配置如下

2、引入jar包

<dependency>
     <groupId>org.springframework.data</groupId>
     <artifactId>spring-data-redis</artifactId>
     <version>1.3.4.RELEASE</version>
 </dependency>

PS:低版本主要为了兼容现在的spring版本和jedis版本

3、实现自己的Spring cache,主要是为了兼容现有redis配置(现有系统redis的实现是自己实现的)

public class ExtendRedisCache implements Cache {

private static final Logger LOG = LoggerFactory.getLogger(ExtendRedisCache.class);

/**
 * Redis
 */
 private RedisTemplate redisTemplate;

/**
 * 缓存名称
 */
 private
String name;

/**
 * 默认超时时间
 */
 private
int timeout;

@Override
 public String getName() {
        return this.name;
    }

@Override
 public Object getNativeCache() {
        return this.redisTemplate;
    }

@Override
 public ValueWrapper get(Object key) {

if (StringUtils.isEmpty(key)) {
            return null;
        }
        Jedis jedis = null;
        try{
            jedis = redisTemplate.getRedisPool().getResource();
            //键
 final String finalKey = getKey(key);

if(StringUtils.isEmpty(finalKey)){
                return null;
            }

byte[] value = jedis.get(finalKey.getBytes());
            if (value == null) {
                return null;
            }

Object object = SerializableUtil.unserialize(value);
            return (object != null ? new SimpleValueWrapper(object) : null);

}catch (Exception e){
            LOG.error("redis has lose connection:",e);
            return null;
        }finally {
            if (null != jedis) {
                jedis.close();
            }
        }

}

/**
 * 获取redis缓存键
 *
 * @param key
 * @return
 */
 private String getKey(Object key) {
        //键
 final String finalKey;

if (key instanceof String) {
            finalKey = this.name + ":" + (String) key;
        } else {
            finalKey = this.name + ":" + key.toString();
        }

return finalKey;
    }

@Override
 public void put(Object key, Object value) {

if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
            return;
        }

Jedis jedis = null;
        try{
            //键
 final String finalKey = getKey(key);

if(!StringUtils.isEmpty(finalKey)){
                jedis = redisTemplate.getRedisPool().getResource();
                redisTemplate.set(finalKey.getBytes(),
SerializableUtil.serialize(value));
               
jedis.expire(finalKey.getBytes(),timeout);
            }
        }catch (Exception e){
            LOG.error("redis has lose connection:",e);
        }finally {
            if (null != jedis) {
                jedis.close();
            }
        }

}

/*
 * 根据Key 删除缓存
 */
 @Override
 public void evict(Object key) {
        if (null != key) {
            try{
                final String finalKey = getKey(key);

if (!StringUtils.isEmpty(finalKey)) {
                    redisTemplate.del(finalKey.getBytes());
                }
            }catch (Exception e){
                LOG.error("redis has lose connection:",e);
            }
        }
    }

/*
 * 清除系统缓存
 */
 @Override
 public void clear() {
        //线上不允许删除所有缓存
 }

public RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }

public void setRedisTemplate(RedisTemplate
redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

public void setName(String name) {
        this.name = name;
    }

public int getTimeout() {
        return timeout;
    }

public void setTimeout(int timeout) {
        this.timeout = timeout;
    }
}

4、添加spring xml配置

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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-3.2.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-3.2.xsd ">

PS:添加红色标注地方

<!-- 启用Spring对基于注解的Cache的支持 -->
<cache:annotation-driven/>

<!-- 缓存管理器 -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
    <property name="caches">
        <set>
            <bean class="ExtendRedisCache">

<property name="redisTemplate" ref="redisTemplate" /> //现有系统的redisTemplate

<property name="name" value="test1" /> //缓存名(结合key)
                <property name="timeout" value="60" /> //过期时间
            </bean>
        </set>
    </property>
</bean>

5、通过注解设置缓存

@Cacheable(value = "test1",key = "#p0")//Cacheable会判断key是否存在,增加redis缓存,key为test1:xxx,这里过期时间在xml里配置

@CachePut(cacheNames="test1",key
= "#p0")//CachePut不会判断key是否存在,直接覆盖,它每次都会触发真实方法的调用,增加redis缓存,key为test1:xxx,,这里过期时间在xml里配置

@CacheEvict(value = "test1",key = "#p1")//删除缓存

其他缓存注解,参考spring cache注解相关定义

spring cache redis的更多相关文章

  1. spring Cache /Redis 缓存 + Spring 的集成示例

    spring Cache https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/ spring+redis 缓存 ht ...

  2. Spring Cache Redis结合遇到的坑

    业务上需要把一些数据放到redis里面,但是系统逻辑代码差不多编写完成了,怎么整?用Spring Cache啊,对既有业务逻辑侵袭极小. 于是尝试调查了一下,遇到一些问题分享一下(本文使用Spring ...

  3. 【快学SpringBoot】Spring Cache+Redis实现高可用缓存解决方案

    前言 之前已经写过一篇文章介绍SpringBoot整合Spring Cache,SpringBoot默认使用的是ConcurrentMapCacheManager,在实际项目中,我们需要一个高可用的. ...

  4. 使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的解决

    应用场景 我们希望通过缓存来减少对关系型数据库的查询次数,减轻数据库压力.在执行DAO类的select***(), query***()方法时,先从Redis中查询有没有缓存数据,如果有则直接从Red ...

  5. spring Cache + Redis 开发数据字典以及自定义标签

    一.数据库表结构 1.  分类表:dict_type 2.  子项表:dict_entry 二.页面维护功能示意图: 1.  分类管理 点击子项管理进入子项管理页面 2.子项管理 三.数据字典添加到缓 ...

  6. Spring Cache扩展:注解失效时间+主动刷新缓存

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  7. Spring Cache For Redis

    一.概述 缓存(Caching)可以存储经常会用到的信息,这样每次需要的时候,这些信息都是立即可用的. 常用的缓存数据库: Redis   使用内存存储(in-memory)的非关系数据库,字符串.列 ...

  8. Spring Boot Cache Redis缓存

    1.集成MyBatis 1.1.引入maven依赖 1.2.生成Mapper 具体可以看MyBatis Generator官网 http://www.mybatis.org/generator/run ...

  9. 【Spring】17、spring cache 与redis缓存整合

    spring cache,基本能够满足一般应用对缓存的需求,但现实总是很复杂,当你的用户量上去或者性能跟不上,总需要进行扩展,这个时候你或许对其提供的内存缓存不满意了,因为其不支持高可用性,也不具备持 ...

随机推荐

  1. 从navicat for mysql导出数据库语句时应该加上的两条语句

    为了不引起编码问题,一般在从navict for mysql导出一个数据库时在文件最前面添加这2句语句: CREATE DATABASE IF NOT EXISTS `` default charac ...

  2. typedef与复杂声明

    参考 [1] http://www.cnblogs.com/bakari/archive/2012/08/28/2659889.html [2]<C专家编程> [3 ]http://www ...

  3. 解决Centos下SSH登录慢的问题

    产生这个问题的原因是:server的sshd会去DNS查找访问client IP的hostname,如果DNS不可用或者没有相关的记录就会花费大量的时间. 1.在server上/etc/hosts文件 ...

  4. 使用em和rem替代px

    rem是指根元素的字体大小,默认情况下html的字体大小为:16px=1rem.而em是相对单位,是基于它的祖先元素计算的. 如果我们不指定html和body的字体大小,要得到12px的rem需要这样 ...

  5. jdk1.8源码包下载并导入到开发环境下助推高质量代码(Eclipse、MyEclipse和Scala IDEA for Eclipse皆适用)(图文详解)

    不多说,直接上干货! jdk1.8 源码, Linux的同学可以用的上. 由于源码JDK是前版本的超集, 所以1.4, 1.5, 1.6, 1.7都可以用的上.     其实大家安装的jdk路径下,这 ...

  6. Unity Shader入门精要学习笔记 - 第9章 更复杂的光照

    转载自 冯乐乐的<Unity Shader入门精要> Unity 的渲染路径 在Unity里,渲染路径决定了光照是如何应该到Unity Shader 中的.因此,如果要和光源打交道,我们需 ...

  7. zoj3765Lights(splay)

    链接 splay的增删改操作. 刚开始对于某段区间首先有了lazy标记时,把其左右孩子给交换了,导致在pushup时又交换了一次而debug了n久. #include <iostream> ...

  8. phpmyadmin消除无法保存最近表的提示

    运行 sudo dpkg-reconfigure phpmyadmin 重新配置phpmyadmin ip选择127.0.0.1,端口3306,"MySQL username for php ...

  9. 访问者模式和php实现

    访问者模式: 表示作用于某个对象结构中的各个元素的操作.它使你可以在不改变各个元素类的前提下定义作用于这些元素的操作. 角色: 1)抽象访问者:为该对象结构中具体元素角色声明一个访问操作接口.该操作接 ...

  10. Android ScrollView嵌套RecyclerView导致在三星s8曲面屏显示不全问题

    当RecyclerView适配显示不全时可以单独给其嵌套一个相对布局!!!(必须是相对布局),这样在曲面屏手机就可以全部显示出来如下图所示 <RelativeLayout android:lay ...