• 【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设计的合理且强大,整个的缓存在项目中才能通用且高效。否则,就像我上面的简单的例子一样,真的是搞笑了。

  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/sxdcgaq8080/p/7228163.html
Copyright © 2020-2023  润新知