springboot-缓存管理

springboot默认使用Simple缓存组件进行缓存管理,Simple组件位于9大缓存组件最后一个(按顺序启用),所以,当没有其他缓存组件引入时,就使用Simple缓存组件,即springboot默认提供的缓存组件

缓存的作用:减少系统查询时间,执行查询时,会先从缓存中查询数据,如果缓存中没有,再去数据库中查询,然后把查询到的数据放到缓存中。(更新操作,会先删除缓存,再存入缓存;删除操作,删除缓存)

一、使用springboot默认的缓存管理

在启动类上加上@EnableCaching ,代表开启Spring Boot基于注解的缓存管理支持

@EnableCaching	//开启Spring Boot基于注解的缓存管理支持
@SpringBootApplication
public class CacheApplication {
	public static void main(String[] args) {
		SpringApplication.run(CacheApplication.class, args);
	}
}

所有缓存注解使用都在Service层下

缓存的注解:

@EnableCaching:开关性注解,在项目启动类或某个配置类上使用此注解后,则表示允许使用注解的方式进行缓存操作

@Cacheable:可用于类或方法上;在目标方法执行前,会根据key先去缓存中查询看是否有数据,有就直接
返回缓存中的key对应的value值。不再执行目标方法;无则执行目标方法,并将方法的返回值
作为value,并以键值对的形式存入缓存

**@CachePut:**可用于类或方法上;在执行完目标方法后,并将方法的返回值作为value,并以键值对的形式存入缓存中

**@CacheEvict:**可用于类或方法上;在执行完目标方法后,清除缓存中对应key的数据(如果缓存
中有对应key的数据缓存的话)

**@Caching:**此注解即可作为@Cacheable、@CacheEvict、@CachePut三种注解中的的任何一种或几种来使用

@CacheConfig:@Cacheable、@CacheEvict、@CachePut这三个注解的cacheNames属性是必
填项(或value属性是必填项,因为value属性是cacheNames的别名属性);如果上述
三种注解都用的是同一个cacheNames的话,那么在每此都写cacheNames的话,
就会显得麻烦。如将@CacheConfig注解就是来配置一些公共属性(如:cacheNames、
keyGenerator等)的值的

缓存注解的常用属性

cacheNames/values:指定缓存组件的名字,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存

key:缓存数据的标识。默认是使用方法参数的值

condition:指定符合条件的情况下才缓存; 如:condition = “#a0>1” 即第一个参数值大于1时才进行缓存

unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到的结果进行判断
如: unless = “#a0”:如果第一个参数值是2,则结果不缓存

				unless = “#result == null”  结果为null不缓存
@Service
public class CommentService {
    @Autowired
    private CommentRepository commentRepository;
    // 根据评论id查询评论信息
//    @Cacheable(cacheNames = "comment")
    @Cacheable(cacheNames = "comment",unless = "#result==null")
    public Comment findById(int comment_id){
        Optional<Comment> optional = commentRepository.findById(comment_id);
        if(optional.isPresent()){
            return optional.get();
        }
        return null;
    }

    // 更新评论信息
    @CachePut(cacheNames = "comment",key = "#result.id")
    public Comment updateComment(Comment comment){
        commentRepository.updateComment(comment.getAuthor(), comment.getaId());
        return comment;
    }
    // 删除评论信息
    @CacheEvict(cacheNames = "comment")
    public void deleteComment(int comment_id){
        commentRepository.deleteById(comment_id);
    }
}

二、springboot整合Redis缓存实现

引入Redis的启动依赖,引入redis依赖后,就代表引入了Redis缓存组件

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

在配置文件中配置Redis

# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=

1.基于注解的Redis缓存实现

在上文中使用Springboot默认的Simple组件的基础上,让实体类序列化就可以了(让实体类实现Serializable接口)。

2.基于API的Redis缓存实现

在service中使用@Autowired注解注入Redis API中常用的RedisTemplate

@Service
public class ApiCommentService {
    @Autowired
    private CommentRepository commentRepository;
    @Autowired
    private RedisTemplate redisTemplate;

    public Comment findById(int comment_id){
        // 先从Redis缓存中查询数据
        Object object =  redisTemplate.opsForValue().get("comment_"+comment_id);
        if (object!=null){
            return (Comment)object;
        }else {
            // 缓存中没有,就进入数据库查询
            Optional<Comment> optional = commentRepository.findById(comment_id);
            if(optional.isPresent()){
                Comment comment= optional.get();
                // 将查询结果进行缓存,并设置有效期为1天
                redisTemplate.opsForValue().set("comment_"+comment_id, comment,1, TimeUnit.DAYS);
                return comment;
            }else {
                return null;
            }
        }
    }
}

RedisTemplate内部使用的序列化方式要求被序列化的实体类继承Serializable接口,实现序列化

注:

  • 基于API的Redis缓存实现不需要@EnableCaching注解开启基于注解的缓存支持。
  • 基于API的Redis缓存实现需要在Spring Boot项目的pom.xml文件中引入Redis依赖启动器,并在配置文件中进行Redis服务连接配置,同时将进行数据存储的Comment实体类实现序列化接口。
  • 缓存测试与基于注解的Redis缓存实现的测试完全一样。

在项目中引入Redis依赖后,Springboot提供的RedisAutoConfiguration自动配置生效,使用默认提供的序列化方式

如果想使用自定义的序列化方式,需要自定义一个配置类,创建一个名为redisTemplate的Bean组件。

@Configuration   // 定义一个配置类
public class RedisConfig {
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        // 使用JSON格式序列化对象,对缓存数据key和value进行转换
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
        // 解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);

        // 设置RedisTemplate模板API的序列化方式为JSON
        template.setDefaultSerializer(jacksonSeial);
        return template;
    }    
}

自定义RedisCacheManager缓存管理器的默认序列化机制

Spring Boot整合Redis组件提供的缓存自动配置类RedisCacheConfiguration,其内部是通过Redis连接工厂RedisConnectionFactory定义了一个缓存管理器RedisCacheManager;同时定制RedisCacheManager时,也默认使用了JdkSerializationRedisSerializer序列化方式。

Springboot1.x版本中,RedisCacheManager是在RedisTemplate的基础上进行构建的,而Springboot2.x版本中,RedisCacheManager是单独进行构建的。因此,Springboot2.x版本中,对RedisTemplate进行自定义序列化机制构建后,仍然无法对RedisCacheManager内部默认序列化机制进行覆盖,也就解释了基于注解的Redis缓存实现仍然会使用JDK默认序列化机制的原因,想要基于注解的Redis缓存也使用自定义序列化机制,需要自定义RedisCacheManager

@Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换
        RedisSerializer<String> strSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jacksonSeial =
                new Jackson2JsonRedisSerializer(Object.class);
        // 解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);

        // 定制缓存数据序列化方式及时效
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(strSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jacksonSeial))
                .disableCachingNullValues();

        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();
        return cacheManager;
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值