• 【转】【redis】3.Spring 集成注解 redis 项目配置使用


    spring-data-redis  项目,配合 spring 特性并集成 Jedis 的一些命令和方法。

    配置redis继承到spring管理项目,使用注解实现redis缓存功能。

    参考:http://www.cnblogs.com/java-class/p/7112541.html

    步骤:1.maven的pom.xml文件导入架包

       2.配置文件添加配置

       3.spring管理bean的生成,xml文件配置

       4. RedisCacheConfig redis自定义的工具类,自定义redis的key生成规则

       5.在你想要做缓存的地方,使用注解进行缓存

    1.maven的pom.xml文件导入架包【本来spring-data-redis架包版本使用最新的2.0.0 ,甚至使用到1.8.4版本,只要保存,启动项目,spring管理的bean都会创建失败,架包冲突的缘故或者其他问题,所以退而求其次,使用1.6.2版本】

    复制代码
    <!-- redis架包 -->
              <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-redis</artifactId>
                <version>1.6.2.RELEASE</version>
              </dependency>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>2.9.0</version>
            </dependency>
    复制代码

    2.配置文件添加配置

    复制代码
    #============================#
    #==== Redis settings ====#
    #============================#
    #redis 服务器 IP
    redis.host=127.0.0.1
    
    #redis 服务器端口
    redis.port=6379
    
    #redis 密码
    redis.pass=398023
    
    #redis 支持16个数据库(相当于不同用户)可以使不同的应用程序数据彼此分开同时又存储在相同的实例上
    redis.dbIndex=0
    
    #redis 缓存数据过期时间单位秒
    redis.expiration=3000
    
    #控制一个 pool 最多有多少个状态为 idle 的jedis实例
    redis.maxIdle=300
    
    #控制一个 pool 可分配多少个jedis实例
    redis.maxActive=600
    
    #当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
    redis.maxWait=1000
    
    #在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的;
    redis.testOnBorrow=true
    复制代码

    3.spring管理bean的生成,xml文件配置

    复制代码
     
        <!-- **************************************************redis********************************************************** -->
        <!-- 配置 JedisPoolConfig 实例 -->
        <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
            <property name="maxIdle" value="${redis.maxIdle}"/>
            <property name="maxTotal" value="${redis.maxActive}"/>
            <property name="maxWaitMillis" value="${redis.maxWait}"/>
            <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
        </bean>
    
        <!-- 配置JedisConnectionFactory -->
        <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
            <property name="hostName" value="${redis.host}"/>
            <property name="port" value="${redis.port}"/>
            <property name="password" value="${redis.pass}"/>
            <property name="database" value="${redis.dbIndex}"/>
            <property name="poolConfig" ref="poolConfig"/>
        </bean>
    
        <!-- 配置RedisTemplate -->
        <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
            <property name="connectionFactory" ref="jedisConnectionFactory"/>
        </bean>
    
        <!-- 配置RedisCacheManager -->
        <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
            <constructor-arg name="redisOperations" ref="redisTemplate"/>
            <property name="defaultExpiration" value="${redis.expiration}"/>
        </bean>
    
        <!-- 配置RedisCacheConfig -->
        <bean id="redisCacheConfig" class="com.sxd.util.RedisCacheConfig">
            <constructor-arg ref="jedisConnectionFactory"/>
            <constructor-arg ref="redisTemplate"/>
            <constructor-arg ref="redisCacheManager"/>
        </bean>
    复制代码

    JedisPoolConfig           jedis连接池配置对象

    JedisConnectionFactory         jedis连接工厂,生成连接对象

    RedisTemplate          RedisTemplate 对 RedisConnection 进行了封装。提供连接管理,序列化等功能,它对 Redis 的交互进行了更高层次的抽象,极大的方便和简化了 Redis 的操作

    RedisCacheManager        做为 redis 统一的调度和管理者

    RedisCacheConfig         RedisCacheConfig extends org.springframework.cache.annotation.CachingConfigurerSupport,自定义redis的key生成规则,如果不在注解参数中注明key=“”的话,就采用这个类中的key生成规则生成key

    4. RedisCacheConfig redis自定义的工具类,自定义redis的key生成规则

    复制代码
    package com.sxd.util;
    
    import java.lang.reflect.Method;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.annotation.CachingConfigurerSupport;
    import org.springframework.cache.annotation.EnableCaching;
    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;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    
    @Configuration
    @EnableCaching
    public class RedisCacheConfig extends CachingConfigurerSupport {
         protected final static Logger log = LoggerFactory.getLogger(RedisCacheConfig.class);
    
            private volatile JedisConnectionFactory mJedisConnectionFactory;
            private volatile RedisTemplate<String, String> mRedisTemplate;
            private volatile RedisCacheManager mRedisCacheManager;
    
            public RedisCacheConfig() {
                super();
            }
    
            public RedisCacheConfig(JedisConnectionFactory mJedisConnectionFactory, RedisTemplate<String, String> mRedisTemplate, RedisCacheManager mRedisCacheManager) {
                super();
                this.mJedisConnectionFactory = mJedisConnectionFactory;
                this.mRedisTemplate = mRedisTemplate;
                this.mRedisCacheManager = mRedisCacheManager;
            }
    
            public JedisConnectionFactory redisConnectionFactory() {
                return mJedisConnectionFactory;
            }
    
            public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
                return mRedisTemplate;
            }
    
            public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
                return mRedisCacheManager;
            }
    
            
            
            @Bean
            public KeyGenerator keyGenerator() {
                return new KeyGenerator() {
                    @Override
                    public Object generate(Object target, Method method,
                            Object... params) {
                        //规定  本类名+方法名+参数名 为key
                        StringBuilder sb = new StringBuilder();
                        sb.append(target.getClass().getName()+"_");
                        sb.append(method.getName()+"_");
                        for (Object obj : params) {
                            sb.append(obj.toString()+",");
                        }
                        return sb.toString();
                    }
                };
            }
            
    }
    复制代码

    5.在你想要做缓存的地方,使用注解进行缓存

    先介绍几个注解

      1》@CacheConfig  配置在类上,cacheNames即定义了本类中所有用到缓存的地方,都去找这个库。只要使用了这个注解,在方法上@Cacheable    @CachePut   @CacheEvict就可以不用写value去找具体库名了。【一般不怎么用】

      2》@Cacheable  配置在方法或类上,作用:本方法执行后,先去缓存看有没有数据,如果没有,从数据库中查找出来,给缓存中存一份,返回结果,下次本方法执行,在缓存未过期情况下,先在缓存中查找,有的话直接返回,没有的话从数据库查找

      3》@CachePut   类似于更新操作,即每次不管缓存中有没有结果,都从数据库查找结果,并将结果更新到缓存,并返回结果

      4》@CacheEvict 用来清除用在本方法或者类上的缓存数据(用在哪里清除哪里)

    例子:

    最直观的表现:首次登录,会有一条数据库的查询语句在控制台。

           退出再登录,不会执行数据库的查询,直接从数据库中取出缓存,登录成功。

    说明:

      ①使用了@Cacheable(value="myUser"),即表示缓存中有,直接从缓存取出,没有的话先从数据库中查出,然后再插入

      ②如果未在类上使用@CacheConfig注解规定数据要缓存到哪个库中,就必须给value一个值,规定数据最后缓存到哪个redis库中

      ③因为redis缓存数据实际就是键值对的形式存储,因此必须给定key-value的key,这里没有给key参数赋值,所以key的生成规则按照上面工具类中规定的key生成的

      ④key-value的value就是本方法的返回值,如果要缓存登录用户信息,本方法需要进行修改,返回user对象就可以缓存到key-value的value中

    *******************************************************************************************************************************************************************

    *******************************************************************************************************************************************************************

    查看一下本次缓存的数据,在redis可视化工具中

    myUser是上面注解中的value,也就是缓存数据库名字叫myUser

    键名key为:xACxEDx00x05tx00Jcom.sxd.controller.WelcomeController_welcome_com.sxd.entity.User@36e69d03,

    键值对value值:xACxEDx00x05tx00x07success

       ①redis以键值对的形式存储缓存数据,而且会对对象进行序列化,如上图可以看到,键和值前面都有一串序列化的字符

       ② RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。JdkSerializationRedisSerializer

       ③SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。

            StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。StringRedisSerializer

            RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。JdkSerializationRedisSerializer

       就是因为序列化策略的不同,即使是同一个key用不同的Template去序列化,结果是不同的。所以根据key去删除数据的时候就出现了删除失败的问题。

       ④在上面配置文件中,没有显式的给出序列化策略,会有默认的序列化策略。

       ⑤如果因为序列化策略不同,可以区显式的设置  具体可参考:http://blog.csdn.net/y666666y/article/details/70212767

    复制代码
    <!-- redis 序列化策略 ,通常情况下key值采用String序列化策略, -->  
    <!-- 如果不指定序列化策略,StringRedisTemplate的key和value都将采用String序列化策略; -->  
    <!-- 但是RedisTemplate的key和value都将采用JDK序列化 这样就会出现采用不同template保存的数据不能用同一个template删除的问题 -->  
    <bean id="stringRedisSerializer"   
        class="org.springframework.data.redis.serializer.StringRedisSerializer" />  
      
    <bean id='redisWriteTemplate' class="org.springframework.data.redis.core.RedisTemplate">  
        <property name="connectionFactory" ref="jedisWriteConnectionFactory" />  
        <property name="keySerializer" ref="stringRedisSerializer" />  
        <property name="hashKeySerializer" ref="stringRedisSerializer" />  
    </bean>
    复制代码

       

    *************************************************************************************************************************************************************************************

    *************************************************************************************************************************************************************************************

    最后给出这几个注解的具体参数以及使用相关配图参考。

    参考自:http://blog.csdn.net/sanjay_f/article/details/47372967

    表 1. @Cacheable 作用和配置方法

    @Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

    @Cacheable 主要的参数
    value 缓存的名称,缓存中具体哪个数据库,在 spring 配置文件中定义,必须指定至少一个 例如:
    @Cacheable(value=”mycache”) 或者 
    @Cacheable(value={”cache1”,”cache2”}
    key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合,或者方法参数列表中的任意一个参数,或者字符串+参数组合

    例如:
    @Cacheable(value=”testcache”,key=”#userName”)

    @Cacheable(value=”testcache”,key=” '字符串'+#userName”)

    condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 例如:
    @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
     
    表 2. @CachePut 作用和配置方法
    @CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
    @CachePut 主要的参数
    value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如:
    @Cacheable(value=”mycache”) 或者 
    @Cacheable(value={”cache1”,”cache2”}
    key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 例如:
    @Cacheable(value=”testcache”,key=”#userName”)
    condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 例如:
    @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
     
    表 3. @CacheEvict 作用和配置方法
    @CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空
    @CacheEvict 主要的参数
    value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如:
    @CachEvict(value=”mycache”) 或者 
    @CachEvict(value={”cache1”,”cache2”}
    key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 例如:
    @CachEvict(value=”testcache”,key=”#userName”)
    condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存 例如:
    @CachEvict(value=”testcache”,
    condition=”#userName.length()>2”)
    allEntries 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 例如:
    @CachEvict(value=”testcache”,allEntries=true)
    beforeInvocation 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 例如:
    @CachEvict(value=”testcache”,beforeInvocation=true)

    *************************************************************************************************************************************************************************************

    *************************************************************************************************************************************************************************************

    spEL表达式的使用方法:http://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/expressions.html

    关于注解实现Redis缓存的方法,只有将key设计的合理且强大,整个的缓存在项目中才能通用且高效。否则,就像我上面的简单的例子一样,真的是搞笑了。

  • 相关阅读:
    ClouderaManager与CDH
    教辅的组成
    国家集训队 小Z的袜子
    国家集训队 旅游
    NOIP2015 子串
    数颜色
    间谍网络
    NOIP2017 逛公园
    APIO2009 抢掠计划
    JLOI2014 松鼠的新家
  • 原文地址:https://www.cnblogs.com/UUUz/p/10900970.html
Copyright © 2020-2023  润新知