Spring搭配Redis作为数据缓存配置实例及知识点说明.md

一、实战配置

1、增加pom文件中redis相关支持
<!-- redis 缓存-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.5.2.RELEASE</version>
        </dependency>
2、增加redis服务器连接相关配置的properties文件
## 最大连接数
redis.maxTotal=10
## 最大空闲数
redis.maxIdle=5
## 最大等待时间
redis.maxWaitMillis=2000
## 测试连接
redis.testOnBorrow=true
## redis服务器地址
redis.host=127.0.0.1
## redis 端口
redis.port=6379
redis.timeout=0
redis.database=1
redis.password=test
redis.testWhileIdle=true 
redis.timeBetweenEvictionRunsMillis=30000  
redis.numTestsPerEvictionRun=50 

2、增加xml相关配置
<!--开启缓存注解扫描-->
<cach:annotation-driven></cach:annotation-driven>
<!-- redis数据源 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大空闲数 -->
        <property name="maxIdle" value="${redis.maxIdle}" />
        <!-- 最大空连接数 -->
        <property name="maxTotal" value="${redis.maxTotal}" />
        <!-- 最大等待时间 -->
        <property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
        <!-- 返回连接时,检测连接是否成功 -->
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>

    <!-- Spring-redis连接池管理工厂 -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <!-- IP地址 -->
        <property name="hostName" value="${redis.host}" />
        <!-- 端口号 -->
        <property name="port" value="${redis.port}" />
<!--        <property name="password" value="${redis.password}" />-->
        <!-- 超时时间 默认2000-->
        <property name="timeout" value="${redis.timeout}" />
        <!-- 连接池配置引用 -->
        <property name="poolConfig" ref="poolConfig" />
        <!-- usePool:是否使用连接池 -->
        <property name="usePool" value="true"/>
        <!--使用哪个redis数据库-->
        <property name="database" value="${redis.database}"></property>
    </bean>

<!--如果使用JSON存储相关数据,就是用这个序列化器-->
    <bean id="jackson2JsonRedisSerializer" class="org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer">
        <constructor-arg value="#{new java.lang.Object().getClass()}"></constructor-arg>
    </bean>

    <!-- 声明redis template-->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
        <property name="valueSerializer" ref="jackson2JsonRedisSerializer"><!--使用JSON存储-->
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
        </property>
        <!--开启事务  -->
        <property name="enableTransactionSupport" value="true"></property>
    </bean>

<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg index="0" ref="redisTemplate"></constructor-arg>
        <property name="usePrefix" value="true"></property>
        <property name="defaultExpiration" value="1000"></property>
    </bean>
<!-- 声明cachManager-->
    <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg index="0" ref="redisTemplate"></constructor-arg>
        <property name="usePrefix" value="true"></property>
        <property name="defaultExpiration" value="1000"></property>
    </bean>
3、使用注解注释那些需要缓存的方法。
public class HeadLineServiceImpl implements HeadLineService {
    Logger logger= Logger.getLogger(HeadLineServiceImpl.class);
    @Autowired
    private HeadLineDao headLineDao;
    @Cacheable(value = "headline",key ="#root.methodName")
        @Override
        public List<HeadLine> getHeadLineList(HeadLine headLineCondition) {
            return headLineDao.queryHeadLine(headLineCondition);

    }
}

二、相关知识点说明--基于注解的缓存支持

1、@Cacheable(有则取,无则存)

@Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略。
与事务一样是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。
@Cacheable可以指定三个属性,value、key和condition

参数 解释 用例
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”)
2、@CachePut(只存不取)

在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

3、@CacheEvict

@CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。下面我们来介绍一下新出现的两个属性allEntries和beforeInvocation。

allEntries属性

allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。

beforeInvocation属性

清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作(可以认为是Spring的后置通知)。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素(可以认为就是Spring通知里面的前置通知)。

4、@Caching

@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

@Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),
   @CacheEvict(value = "cache3", allEntries = true) })
   public User find(Integer id) {
      returnnull;
   }

5、在自定义key时可以使用SpEL表达式进行指定,具体关于SpEL的相关知识后续补充,Spring还提供了root对象用来生产key.

属性名 描述 用例
methodName 当前方法名 #root.methodName
method 当前方法 #root.method.name
target 当前被调用的对象 #root.target
targetClass 当前被调用的对象的class #root.targetClass
args 当前方法参数组成的数组 #root.args[0]
caches 当前被调用的方法使用的Cache #root.caches[0].name
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容