SpringBoot修改缓存为redis与SpringBoot缓存注解用法详解

1.引入依赖

<!--开启 cache 缓存-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>

2.在application.yml文件中配置redis

spring:
  redis:
    host: 127.0.0.1
    port: 6379
      # 连接池配置,2.0中直接使用jedis或者lettuce配置连接池
      jedis:
        pool:
          # 最大空闲连接数
          max-idle: 500
          # 最小空闲连接数
          min-idle: 50
          # 等待可用连接的最大时间,负数为不限制
          max-wait:  -1s
          # 最大活跃连接数,负数为不限制
          max-active: -1

3.定义一个Redis配置类

@Configuration
@EnableCaching 
public class RedisConfig {
    @Bean //在没有指定缓存Key的情况下,key生成策略
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuffer sb = new StringBuffer();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        //RedisCacheManager cacheManager = RedisCacheManager.create(factory);//通过RedisCacheManager的静态方法create 产生的cacheManager只是使用Spring提供的默认配置
        //通过自定义的方式构建cacheManager
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        config.entryTtl(Duration.ofMinutes(60 * 72)).//设置缓存过期时间
                disableCachingNullValues();//不缓存空值
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory) //使用自定义的缓存配置初始化
                .build();
        return cacheManager;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

@EnableCaching作用

@EnableCaching注解是spring framework中的注解驱动的缓存管理功能。
很多时候系统的瓶颈都在一些比较复杂的IO操作,例如读取数据库,如果一些比较稳定的数据,一般的解决方案就是用缓存。spring boot提供了比较简单的缓存方案。只要使用 @EnableCaching即可完成简单的缓存功能。
作用:开启缓存注解支持(必须作用在缓存配置类上才有效)

4 缓存注解

@Cacheable

作用:主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 
Spring 在执行 @Cacheable 标注的方法前先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,执行该方法并将方法返回值放进缓存。

@Cacheable可以指定三个属性value、key和condition:
     value:缓存的名称,在spring配置文件中定义,必须指定至少一个
	 key:缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合
	 condition:缓存的条件,可以为空,使用SpEL编写,返回true或者false只有为true才进行缓存

例如:

@Cacheable(value = "cache",key = "#key")
 public String setCache(String key,String value){
     return value;
}
调用方法传入key:aa value:bbbb,可以看见redis中存入的值,key的名字的话由value+key组成,存储数据类型为String,当我再次调用这个方法传入key:aa value:cccc,获取出来的值是bbbb,所以标注了@Cacheable的方法会先去查询缓存中有没有数据,如果有数据,直接返回数据,不会执行方法体的内容;若没有数据,就会执行方法并将返回值放入缓存。

在这里插入图片描述

@CachePut

@Cacheable 类似,不管缓存中是否存在数据,都会执行方法并将返回值存入到缓存, 主要用于数据新增和修改方法

@CacheEvict

作用:主要针对方法配置,能够根据一定的条件对缓存进行清空

@CacheEvict可以指定五个属性value、key、condition、allEntries和beforeInvocation:
	value:缓存的名称,在spring配置文件中定义,必须指定至少一个
	key:缓存的key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合
	condition:缓存的条件,可以为空,使用SpEL编写,返回true或者false,只有为true才进行缓存
	allEntries:是否清空所有缓存内容,缺省为false,如果指定为true,则方法调用后将立即清空所有缓存
	beforeInvocation:是否在方法执行前就清空,缺省为false,如果指定为true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存

例如:

@CacheEvict(value = "cache",key = "#key")
    public void del(String key){
    }
调用这个方法,就会将指定的key的数据删除掉
@CacheEvict(value = "cache",allEntries =true)
    public void del(String key){
    }
调用这个方法,清除cache中所有缓存
@CacheEvict(value = "cache",condition = "#key.length()<3")
    public void del(String key){
    }
当key的长度满足条件的时候,就会在redis中删除对应的缓存

@CacheConfig

所有的@Cacheable() 里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完那就省事了,所以,有了@CacheConfig这个配置,如果你在你的方法写别的名字,那么依然以方法的名字为准。

例如:

@CacheConfig("aa")
public class SpringCacheDemo {
  @Cacheable
  public void del(String key){
    }
}

@Caching

作用:有时候我们可能组合多个Cache注解使用;比如用户新增成功后,如果我们要通过用户的属性值获取用户的话,就可以使用到这个标签
属性:
	cacheable:添加@Cacheable注解
	put:添加 @CachePut 注解

例如:

@Caching(
            cacheable = {
                    @Cacheable(value = "user", key = "#key")
            },
            put = {
                    @CachePut(value = "user", key = "#result.id", condition = "#result != null"),
                    @CachePut(value = "user", key = "#result.name", condition = "#result != null"),
                    @CachePut(value = "user", key = "#result.sex", condition = "#result != null")
            }
    )
    public  User setCache(String key){
        User user = new User("11", "22", "33");
        return user;
    }
    
@Cacheable(value = "user",key = "#key")
    public  User getCache(String key){
        return null;
    }
当我执行setCache()方法的时候,就可以通过传入用户的(id,name,sex)getCache()方法中获取到存入到缓存中的user对象

下图为通过sex可以获取到user:
在这里插入图片描述
redis中存入数据形式:
在这里插入图片描述

@Cacheable与@CachePut区别

@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。所以@CachePut一般用于存值,@Cacheable用于取值。

Spring Cache提供了一些供我们使用的SpEL上下文数据,下表直接摘自Spring官方文档:

名称位置描述示例
methodNameroot对象当前被调用的方法名root.methodName
methodroot对象当前被调用的方法root.method.name
targetroot对象当前被调用的目标对象root.target
targetClassroot对象当前被调用的目标对象类root.targetClass
argsroot对象当前被调用的方法的参数列表root.args[0]
cachesroot对象当前方法调用使用的缓存列表(如@Cacheable(value={“cache1”, “cache2”})),则有两个cacheroot.caches[0].name
argument name执行上下文当前被调用的方法的参数,如findById(Long id),我们可以通过#id拿到参数,如果为findById(User user),如右边所示user.id
result执行上下文方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,'cache evict’的beforeInvocation=false)result

使用中碰到的问题:

使用缓存注解一直不能生效,存入不到redis:

 	@RequestMapping("/set")
    public Object setCache( String key){
        return new SpringCacheDemo().setCache(key);
    }
因为@Cacheable这些注解是使用AOP代理实现的,必须走代理才能生效;
通过创建对象来使用缓存方法,这样就会导致一个问题,创建对象方法调用对象的缓存方法不会走代理,就不能正常创建缓存,所以每次都只是执行了方法体本身,并没有通过AOP对方法进行增强。

解决方式:

通过Spring注入:

@Autowired
SpringCacheDemo springCacheDemo;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值