当前位置 : 主页 > 编程语言 > java >

Spring Cache 整合 Redis 做缓存使用~ 快速上手~

来源:互联网 收集:自由互联 发布时间:2022-10-26
Spring Cache 介绍 看到​​Spring​​就知道这是​​Spring​​生态中的东西,其实缓存数据的技术并不少,Spring 官方此举是引入 Spring Cache 来帮我们管理缓存,使用注解,简化很多操作。

Spring Cache 介绍

看到​​Spring​​就知道这是​​Spring​​生态中的东西,其实缓存数据的技术并不少,Spring 官方此举是引入 Spring Cache 来帮我们管理缓存,使用注解,简化很多操作。

当然使用 Spring Cache 也有优缺点的.

优点

  • 使用注解,简化操作
  • 缓存管理器,方便多种实现切换缓存源,如​​Redis,Guava Cache等​​
  • 支持事务, 即事物回滚时,缓存同时自动回滚

缺点

  • 不支持TTL,不能为每个 key 设置单独过期时间​​expires time​​,
  • 针对多线程没有专门的处理,所以当多线程时,是会产生数据不一致性的。(同样,一般有高并发操作的缓存数据,都会特殊处理,而不太使用这种方式)

Spring Cache 快速上手

不想那么多,先快速上个手,再接着详细说一说。

​​SpringBoot​​ 常规步骤:

  • 导入依赖
  • 修改配置文件(这一步也可以直接写在第三步)
  • 编写​​xxxxConfig​​ 或者是​​Enablexxxx​​

前期准备

这也一样的,另外我这里使用的是 ​​Spring Cache​​ 整合 ​​Redis​​ 做缓存。

<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>

一般看到是​​spring-boot-starter​​开头的依赖,都可以大胆猜测他们是有一个​​xxxProperties​​配置类与之对应的。

修改配置文件:

spring:
redis:
host: xxxxx
password: xxxx
#指定缓存类型
cache:
type: redis
#指定存活时间(ms)
redis.time-to-live: 86400000
#是否缓存空值,可以防止缓存穿透
redis.cache-null-values: true

与之对应的配置类,大伙可以自己去看看,能配置些啥

Spring Cache 整合 Redis 做缓存使用~ 快速上手~_redis

另外,在这里进行配置的,在我们的编写​​xxxConfig​​类的时候,也同样可以在那里配置。

因为也要配置​​Redis​​的配置,就把之前文章里面的东西都粘贴过来了~

/**
* @description:
* @author: Ning Zaichun
* @date: 2022年10月22日 23:21
*/
@EnableConfigurationProperties(CacheProperties.class)
@EnableCaching
@Configuration
public class MyRedisConfig {

private final Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer(Object.class);
{
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
}
/**
* 1.原来的配置类形式
* @ConfigurationProperties(prefix = "spring.cache")
* public class CacheProperties {
* 因为这个并没有放到容器中,所以要让他生效 @EnableConfigurationProperties(CacheProperties.class)
* 因为这个和配置文件已经绑定生效了
* @return
*/
@Bean
RedisCacheConfiguration redisCacheConfiguration(CacheProperties CacheProperties) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
//因为key的序列化默认就是 StringRedisSerializer
// config = config.serializeKeysWith(RedisSerializationContext
// .SerializationPair
// .fromSerializer(new StringRedisSerializer()));

config = config.serializeValuesWith(RedisSerializationContext
.SerializationPair
.fromSerializer(serializer));

CacheProperties.Redis redisProperties = CacheProperties.getRedis();
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}

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

//设置value 值的序列化
redisTemplate.setValueSerializer(serializer);
//key的序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());

// set hash hashkey 值的序列化
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// set hash value 值的序列化
redisTemplate.setHashValueSerializer(serializer);

redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}

@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
}

前期准备结束,直接上手使用~

开始使用

controller-- service--mapper 一路到底,我这里是连接了数据库,只是测试的话,直接在service 的返回结果中存一串字符串即可。

/**
* @description:
* @author: Ning Zaichun
* @date: 2022年09月06日 22:16
*/
@RestController
@RequestMapping("/cache")
@RequiredArgsConstructor
public class CacheController {

private final IUseSpringCache useSpringCache;

@GetMapping("/test")
public String getTest() {
return useSpringCache.getTest();
}


@GetMapping("/test2")
public String getTest2() {
return useSpringCache.getTest2();
}


@GetMapping("/test/clear")
public String clearTest() {
useSpringCache.clearTest();
return "clearTest";
}

@GetMapping
public List<MenuEntity> getMenuList() {
return useSpringCache.getMenuList();
}

@GetMapping("/clear")
public String updateMenu() {
MenuEntity menuEntity = new MenuEntity();
menuEntity.setCatId(33L);
menuEntity.setName("其他测试数据");
useSpringCache.updateMenuById(menuEntity);
return "成功清空缓存";
}
} /**
* @description:
* @author: Ning Zaichun
* @date: 2022年09月21日 20:30
*/
public interface IUseSpringCache {

String getTest();

String getTest2();

void clearTest();

List<MenuEntity> getMenuList();

void updateMenuById(MenuEntity menuEntity);
} /**
* @description:
* @author: Ning Zaichun
* @date: 2022年09月21日 20:30
*/
@Service
@RequiredArgsConstructor
public class UseSpringCacheImpl implements IUseSpringCache {

private final MenuMapper menuMapper;

@Cacheable(value = {"menu"}, key = "'getMenuList'")
@Override
public List<MenuEntity> getMenuList() {
System.out.println("查询数据库======");
List<MenuEntity> menuEntityList = menuMapper.selectList(new QueryWrapper<>());
return menuEntityList;
}

/**
* 级联更新所有关联的数据
*
* @param menuEntity
* @CacheEvict:失效模式
* @CachePut:双写模式,需要有返回值 1、同时进行多种缓存操作:@Caching
* 2、指定删除某个分区下的所有数据 @CacheEvict(value = "menu",allEntries = true)
* 3、存储同一类型的数据,都可以指定为同一分区
*/
// @Caching(evict = {
// @CacheEvict(value = "category",key = "'getLevel1Categorys'"),
// @CacheEvict(value = "category",key = "'getCatalogJson'")
// })
@CacheEvict(value = "menu", allEntries = true) //删除某个分区下的所有数据
@Transactional(rollbackFor = Exception.class)
@Override
public void updateMenuById(MenuEntity menuEntity) {
System.out.println("清空缓存======");
menuMapper.updateById(menuEntity);
}

@Cacheable(value = {"test"}, key = "#root.methodName")
@Override
public String getTest() {
System.out.println("测试查询了数据库");
return "我是测试缓存数据";
}

@Cacheable(value = {"test"}, key = "'getTest2'")
@Override
public String getTest2() {
System.out.println("测试查询了数据库2");
return "我是测试缓存数据2";
}

@Caching(evict = {
@CacheEvict(value = "test",key = "'getTest'")
})
@Override
public void clearTest() {
System.out.println("清空了test缓存");
}
}

测试

上面就是简单的使用,上面的注解啥的,马上就开说哈

先讲讲案例中的两个删除缓存的注解

@CacheEvict(value = "menu", allEntries = true)
@Caching(evict = {
@CacheEvict(value = "test",key = "'getTest'")
})

两种方式,​​allEntries = true​​表示直接清空掉整个分区,

而第二种方式,只会清掉​​getTest​​的分区。

在​​Redis​​的缓存,它的格式是这样的。

Spring Cache 整合 Redis 做缓存使用~ 快速上手~_redis_02

采用第二种方式时,只会清理掉​​getTest​​的分区。

变成下面这样:

Spring Cache 整合 Redis 做缓存使用~ 快速上手~_缓存_03

上面的案例,我只是使用最简单的方式使用了一下 ​​Spring Cache​​

但其实注解上远不止这么一点东西,接下来慢慢说一说

上一篇:使用LEFT JOIN 统计左右存在的数据
下一篇:没有了
网友评论