Spring Boot缓存管理(Redis)

1.项目前期配置

1.1 配置pom.xml 

<!-- 引入Spring整合Redis的依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

 1.2 配置 application.yml 文件

spring:
  # MySQL数据库连接配置
  datasource:
    url: jdbc:mysql:///springbootdata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
    username: root
    password: 123
  jpa:
    # 显示使用JPA进行数据库查询的SQL语句
    show-sql: true
  # 配置Redis服务器
  redis:
    host: 192.168.93.100
    port: 6379
    # 密码可以为空,但不能不写
    password:

1.3 主类加入 @EnableCaching 注解

@EnableCaching      // 开启了SpringBoot基于注解的缓存管理实现(Spring技术实现的)
@SpringBootApplication
public class SpringbootCacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootCacheApplication.class, args);
    }

}

2 Spring Boot缓存注解实现

2.1 @EnableCaching注解 

@EnableCaching是由Spring框架提供的,Spring Boot框架对该注解进行了继承,该注解需要配置在类 上(在Spring Boot中,通常配置在项目启动类上),用于开启基于注解的缓存支持。 

默认查看下表内存库

 

2.2 @Cacheable注解 

一般用于查询;表示将方法的返回值缓存到内存中, key 默认为参数值;cacheNames:命名空间名

 @Cacheable注解也是由Spring框架提供的,可以作用于类或方法(通常用在数据查询方法上),用于 对方法的查询结果进行缓存存储。@Cacheable注解的执行顺序是,先进行缓存查询,如果为空则进行 方法查询,并将结果进行缓存;如果缓存中有数据,不进行方法查询,而是直接使用缓存数据。 Cacheable注解提供了多个属性,用于对缓存存储进行相关配置,具体属性及说明如下表所示。 

 

 2.3 @CachePut注解

一般用于修改;#result 表示返回值,如果是对象可以打点获取值,用法和@Cacheable注解一致

@CachePut注解是由Spring框架提供的,可以作用于类或方法(通常用在数据更新方法上),该注解的 作用是更新缓存数据。@CachePut注解的执行顺序是,先进行方法调用,然后将方法结果更新到缓存 中。 

@CachePut注解也提供了多个属性,这些属性与@Cacheable注解的属性完全相同。 

 2.4 @CacheEvict注解

一般用于删除;删除 命名空间为 cacheNames 属性值 ,key 属性值 的 内存数据,会立即删除内存中的 key 

@CacheEvict注解是由Spring框架提供的,可以作用于类或方法(通常用在数据删除方法上),该注解 的作用是删除缓存数据。@CacheEvict注解的默认执行顺序是,先进行方法调用,然后清除缓存。 @CacheEvict注解提供了多个属性,这些属性与@Cacheable注解的属性基本相同。除此之外, @CacheEvict注解额外提供了两个特殊属性allEntries和beforeInvocation,其说明如下。 

1.allEntries属性

allEntries属性表示是否清除指定缓存空间中的所有缓存数据,默认值为false(即默认只删除指定key对 应的缓存数据)。例如@CacheEvict(cacheNames="comment",allEntries= true)表示方法执行后会删除 缓存空间comment中所有的数据。 

2.beforeInvocation属性

beforeInvocation属性表示是否在方法执行之前进行缓存清除,默认值为false(即默认在执行方法后再 进行领存清除)例如@CacheEvict(cacheNames="comment",beforeInvocation=true)表示会在方法执 行之前进行缓存清除。

需要注意的是,如果将@CacheEvict注解的beforeInvocation属性设置为true,会存在一定的弊端。例 如在进行数据删除的方法中发生了异常,这会导致实际数据并没有被删除,但是缓存数据却被提前清除 了。 

2.5 @Caching注解

上三个的组合注解;用法例 :

@Caching(cacheable = {@Cacheable(cacheNames = "comment", key = "#comment_id")},put = {@CachePut(cacheNames = "comment", key = "#result.author")})

2.6 @CacheConfig注解 

用于 Service 层,类上 表示配置上面几个注解的公有属性

@CacheConfig注解作用于类,主要用于统筹管理类中所有使用@Cacheable、@CachePut和 @CacheEvict注解标注的方法中的公共属性,这些公共属性包括cacheNames、keyGenerator、 cacheManager和cacheResolver。 

2.7 示例: 

package com.example.springboot_cache.service.impl;

import com.example.springboot_cache.domain.Comment;
import com.example.springboot_cache.repository.CommentRepository;
import com.example.springboot_cache.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;

import java.util.Optional;

//@Service
@CacheConfig(cacheNames = "comment")
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentRepository commentRepository;

    @Override
    // @Cacheable(cacheNames = "comment")    // 表示将方法的返回值缓存到内存中
    // @Caching(cacheable = {@Cacheable(key = "#comment_id")})
    @Cacheable(unless = "#result == null")
    public Comment findByid(int comment_id) {
        Optional<Comment> optional = commentRepository.findById(comment_id);
        if (optional.isPresent()) {
            return optional.get(); // 获取 optional 中的comment对象
        }
        return null;
    }

    @Override
    @CachePut(key = "#result.id")
    // @Caching(put = {@CachePut(key = "#result.author")})
    public Comment updateComment(Comment comment) {
        commentRepository.updateComment(comment.getAuthor(),comment.getId());
        return comment;
    }

    @Override
    @CacheEvict() // 默认key为 形参 comment_id 的值
    public void deleteCommentById(int comment_id) {
        commentRepository.deleteById(comment_id);
    }
}

3 Spring Boot缓存API实现

直接使用:

@Autowired
// 简化了Redis操作的模板类,底层分装了Jedis。通过RedisTemplate类完成Redis增删改查操作
private RedisTemplate redisTemplate;

在Spring Boot整合Redis缓存实现中,除了基于注解形式的Redis缓存实现外,还有一种开发中常用的方 式——基于API的Redis缓存实现。下面我们通过Redis API的方式讲解Spring Boot整合Redis缓存的具体 实现。

 3.1 示例

package com.example.springboot_cache.service.impl;

import com.example.springboot_cache.domain.Comment;
import com.example.springboot_cache.repository.CommentRepository;
import com.example.springboot_cache.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Service
public class APICommentServiceImpl implements CommentService {

    @Autowired
    private CommentRepository commentRepository;
    @Autowired
    // 简化了Redis操作的模板类,底层分装了Jedis。通过RedisTemplate类完成Redis增删改查操作
    private RedisTemplate redisTemplate;

    @Override
    public Comment findByid(int comment_id) {
        // 通过RedisTemplate查询缓存中的数据
        //
        Object obj = redisTemplate.opsForValue().get("comment_" + comment_id);
        if(obj != null) {
            return (Comment) obj;
        }else {
            Optional<Comment> optional = commentRepository.findById(comment_id);
            if (optional.isPresent()) {
                Comment comment = optional.get();
                // redisTemplate.opsForValue().set("comment_" + comment_id,comment);
                redisTemplate.opsForValue().set("comment_" + comment_id, comment, 1, TimeUnit.DAYS);
                return comment;
            }
            return null;
        }
    }

    @Override
    public Comment updateComment(Comment comment) {
        commentRepository.updateComment(comment.getAuthor(), comment.getId());
        redisTemplate.opsForValue().set("comment_" + comment.getId(),comment);
        return comment;
    }

    @Override
    public void deleteCommentById(int comment_id) {
        commentRepository.deleteById(comment_id);
        redisTemplate.delete("comment_" + comment_id);
    }
}

 4 自定义Redis缓存序列化机制

 4.1 配置类

package com.example.springboot_cache.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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
public class RedisConfig {

    @Bean
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();

        // 设置 Redis 模板类的连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        // 使用 JSON 格式序列化对象,将对象的数据缓存成key-value结构
        Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        // 解决查询数据转化的异常问题
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jsonRedisSerializer.setObjectMapper(mapper);

        // 设置RedisTemlate模板的序列化存储方式
        redisTemplate.setDefaultSerializer(jsonRedisSerializer);

        return redisTemplate;
    }

    // 注解开发
//    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 设置value的序列化方式
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer(); // 设置key的序列化方式

        // 创建RedisCacheConfiguration 对象
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1))       // 配置缓存数据默认
                // 指定key序列化
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer))
                .disableCachingNullValues();    // null 值不参与序列化

        // 创建 RedisCacheManager 并作为返回值
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();

        return redisCacheManager;
    }
}

 5. 详细内容

百度网盘链接: https://pan.baidu.com/s/1fQ9tZAXE_ygtuv3mUPNlYw?pwd=m29s

提取码: m29s

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值