1、两者作用

首先说明这两个注解都是spring提供的,可以结合不同的缓存技术使用。
@EnableCaching是开启缓存功能,作用于缓存配置类上或者作用于springboot启动类上。
@Cacheable 注解在方法上,表示该方法的返回结果是可以缓存的。也就是说,该方法的返回结果会放在缓存中,以便于以后使用相同的参数调用该方法时,会返回缓存中的值,而不会实际执行该方法。如果缓存过期,则重新执行。

结合redis介绍如何使用

1、首先给出redis的配置类

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
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;

@Configuration
@EnableCaching
public class BootRedisConfig{
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory){
        //Duration.ofSeconds(120)设置缓存默认过期时间120秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(120));
        //解决使用@Cacheable,redis数据库value乱码
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();
        return cacheManager;
    }

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        //连接redis服务器
        redisTemplate.setConnectionFactory(factory);

        //将redis默认序列化方式转换为json格式
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }
}

2、准备个实体类:

@Data
public class Student implements Serializable {
    private String name;
    private int age;
}

3、做个简单测试:

@RestController
@RequestMapping("/cache")
public class CacheController {    
    @GetMapping("/findById/{id}")
    @Cacheable("student00")
    public Student findById(@PathVariable("id")String id){
        Student student = new Student();
        student.setAge(23);
        student.setName("zhangsan");
        return student;
    }
}

执行findById,@Cacheable(“student00”)使返回结果缓存到redis(配置了redis),结果以key为student00::{传入参数id},value为返回的student对象。下次执行该方法时先根据id与student00拼串进行判断缓存中是否有对应的key,有的话直接返回结果。
在这里插入图片描述

定义多个缓存名,会存多份

@GetMapping("/findByIds/{id}")
@Cacheable({"student01","student02"})
public Student findByIds(@PathVariable("id")String id){
    Student student = new Student();
    student.setAge(25);
    student.setName("lisi");
    return student;
}

在这里插入图片描述

另外,默认的key拼串并不是很友好,调用的方法只有一个参数时,会自动使用@Cacheable(“student00”)中设置的student00 + :: + 传入参数;当多个参数时:

@GetMapping("/findById/{id}/{name}")
@Cacheable("student00")
public Student findById(@PathVariable("id")String id,@PathVariable("name")String name){
    Student student = new Student();
    student.setAge(23);
    student.setName("zhangsan");
    return student;
}

在这里插入图片描述

为了更直观,可以显式指定key,利用SpEL(Spring Expression Language,Spring 表达式语言)来动态拼接key:

@Cacheable(value = "student00",key = "'id-name:' + #id + '-' + #name")

在这里插入图片描述

此外,@Cacheable()中还可加入sync = true/false属性,
在一个多线程的环境中,某些操作可能被相同的参数并发地调用,这样同一个 value 值可能被多次计算(或多次访问 db),这样就达不到缓存的目的。针对这些可能高并发的操作,我们可以使用 sync 参数来告诉底层的缓存提供者将缓存的入口锁住,这样就只能有一个线程计算操作的结果值,而其它线程需要等待,这样就避免了 n-1 次数据库访问。

sync = true 可以有效的避免缓存击穿的问题。

另外还可加入缓存判断条件,对方法传入参数进行判断,满足条件则执行缓存查询;不满足条件则直接把该方法当作普通方法使用,不会进行缓存判断,也不会把结果放近缓存。

condition = “#id > 1” //只有id>1才走缓存

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐