【第三章】SpringBoot2.x集成Redis之-缓存

前面讲了【第二章】SpringBoot2.x集成Redis , 以及SpringBoot中redis的基本使用.
本篇主要讲Redis数据库作为SpringBoot中缓存(Cache)的基本使用.

引入依赖

<!-- redis starter -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- lettuce pool 缓存连接池 -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
</dependency>

不再需要引入其他依赖,SpringBoot导入spring-boot-starter-data-redis时,
CacheManager默认使用RedisCache.

如果项目不是以Redis作为缓存,则需引入:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

application.yml配置

spring:
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # Redis服务器连接端口
    port: 6379
    # Redis服务器地址
    host: 127.0.0.1
    # Redis服务器连接密码(默认为空)
    password: 123456
    # 连接超时时间(毫秒)
    timeout: 5000
    lettuce:
      # 关闭超时时间
      shutdown-timeout: 100
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: 10000
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池中的最小空闲连接
        min-idle: 0

开启缓存@EnableCaching, 并配置CacheManager,KeyGenerator

  • @EnableCaching: 开启缓存
  • CacheManager: Spring缓存管理器
  • KeyGenerator: Redis 缓存键生成策略, Spring 默认的DefaultKeyGenerator根据参数列表生成Key,当参数列表的值相同时是一样的 就会造成获取到错误的缓存数据
import com.alibaba.fastjson.JSONObject;
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.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.StringJoiner;

/**
 * @Title: RedisCacheConfig
 * @Description: TODO(reids缓存配置)
 * @Author flyingkid
 * @Date 2019/6/5下午 11:36
 */
@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {


    /**
     * @description TODO 缓存key前缀
     */
    private static final String keyPrefix = "CACHE:";

    /**
     * 缓存生成key的策略
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringJoiner joiner = new StringJoiner(":",keyPrefix,"");
            joiner.add(target.getClass().getSimpleName());
            joiner.add(method.getName());

            for (Object param : params) {
                joiner.add(JSONObject.toJSONString(param));
            }
            return joiner.toString();
        };
    }

    /**
     * RedisTemplate配置
     */
    @Bean
    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(keySerializer());
        redisTemplate.setHashKeySerializer(keySerializer());
        redisTemplate.setValueSerializer(valueSerializer());
        redisTemplate.setHashValueSerializer(valueSerializer());
        return redisTemplate;
    }


    /**
     * 管理缓存
     */
    @Bean
    @Primary
    public CacheManager cacheManager(LettuceConnectionFactory factory){
        //缓存配置对象
        RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                //设置缓存的默认超时时间:30分钟
                .entryTtl(Duration.ofMinutes(30L))
                //如果是空值,不缓存
                .disableCachingNullValues()
                //设置key序列化器
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                //设置value序列化器
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer((valueSerializer())));

        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
                .cacheDefaults(cacheConfig).build();
    }
    /**
     * key序列化
     */
    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }
    /**
     * value序列化
     */
    private RedisSerializer<Object> valueSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }
}

注: StringJoiner是 java8对String字符串拼接提供的工具类, new StringJoiner(":",keyPrefix,"");
构造器第一个参数表示拼接以冒号分隔,参数二是前缀,参数三是后缀. 感兴趣的小伙伴可以阅读下java.util.StringJoiner源码.

缓存基本使用

import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * @ClassName: ExampleService
 * @Description: TODO redis缓存
 * @Author: 爱飘de小子
 */
@Slf4j
@Service
@CacheConfig(keyGenerator = "keyGenerator") //这是本类统一key生成策略
public class ExampleService {

    /**
     * @description TODO  添加缓存
     * @param name
     */
    @Override
    @Cacheable(value = "addCache")
    public String addCache(String name) {
        return "爱飘de小子";
    }

    /**
     * @description TODO 删除缓存
     * @param name
     */
    @Override
    @CacheEvict(value = "addCache",allEntries=true)
    public void delCache(String name) {

    }
}



缓存注解详解

@Cacheable

添加在方法上,根据条件添加缓存

  • value: 缓存的名称,不能为空
  • cacheNames: 缓存的名称,和value二选一
  • key: 缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL
  • keyGenerator: 指定key的生成策略
  • cacheManager: 指定缓存管理器
  • cacheResolver: 指定获取解析器
  • condition: 条件符合则缓存
  • unless: 条件符合则不缓存
  • sync: 是否使用异步模式 默认false

@CachePut

添加在方法上,根据条件添加缓存

@CachePut作用和@Cacheable类似,区别是@Cacheable没有缓存数据会执行方法后,把结果缓存起来,第二次调用方法不执行方法,直接从缓存中获取数据并返回.
@CachePut每次都会执行方法,不管缓存中有没有数据,都会把结果缓存.

@CacheEvict

添加在方法上,根据条件清空缓存.

  • value: 缓存名称,不能为空
  • cacheNames: 缓存的名称,与value二选一
  • keyGenerator: key的生成器。key/keyGenerator二选一使用
  • condition: 触发条件,支持SpEL
  • allEntries: true表示清除value中的全部缓存,默认为false
  • beforeInvocation: 是否在方法执行前就清空 默认false
  • cacheManager: 指定缓存管理器
  • cacheResolver: 或者指定获取解析器

@CacheConfig

作用在类上,为本类的缓存注解配置全局属性

  • cacheNames: 缓存名称
  • keyGenerator: key的生成器
  • cacheManager: 缓存管理器
  • cacheResolver: 获取解析器

@Caching

组合多个缓存注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {
    Cacheable[] cacheable() default {};

    CachePut[] put() default {};

    CacheEvict[] evict() default {};
}

Caching注解中Cacheable,CachePut,CacheEvict都是数组类型. 可以满足方法添加或者删除多个缓存.

上一篇:SpringBoot2+Druid+JdbcTemplate+MySql实现增删改查


下一篇:springboot2.x 整合redis集群的几种方式