【SpringBoot 技术专题】「Cache 缓存组件」Redis 缓存使用技巧及注解大全(1)

public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable(cacheNames=“books”, key=“#isbn.rawNumber”)

public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable(cacheNames=“books”, key=“T(someType).hash(#isbn)”)

public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable 还可以设置根据条件判断是否需要缓存

condition:取决于给定的参数是否满足条件

unless:取决于返回值是否满足条件,返回 false 时候说明走缓存

以下是一个简单的例子:

@Cacheable(cacheNames=“book”, condition=“#name.length() < 32”)

public Book findBook(String name)

@Cacheable(cacheNames=“book”, condition=“#name.length() < 32”, unless="

#result.hardback")

public Book findBook(String name)

@Cacheable 还可以设置:

keyGenerator(指定 key 自动生成方法)

cacheManager(指定使用的缓存管理)

cacheResolver(指定使用缓存的解析器)等,这些参数比较适合全局设置,这里就不多做介绍了。

@CachePut

@CachePut:当需要更新缓存而不干扰方法的运行时 ,可以使用该注解。也就是说,始终执行该方法,并将结果放入缓存,注解参数与 @Cacheable 相同。 以下是一个简单的例子:

@CachePut(cacheNames=“book”, key=“#isbn”)

public Book updateBook(ISBN isbn, BookDescriptor descriptor)

通常强烈建议不要对同一方法同时使用 @CachePut 和 @Cacheable 注解,因为它们具有不同的行为。可能会产生不可思议的 BUG 哦。

@CacheEvict

@CacheEvict:删除缓存的注解,这对删除旧的数据和无用的数据是非常有用的。这里还多了一个参数(allEntries),设置 allEntries=true 时,可以对整个条目进行批量删除。 以下是个简单的例子:

@CacheEvict(cacheNames=“books”)

public void loadBooks(InputStream batch)

//对cacheNames进行批量删除

@CacheEvict(cacheNames=“books”, allEntries=true)

public void loadBooks(InputStream batch)

@Caching

@Caching:在使用缓存的时候,有可能会同时进行更新和删除,会出现同时使用多个注解的情况.而 @Caching 可以实现。 以下是个简单的例子:

@Caching(evict = { @CacheEvict(“primary”),

@CacheEvict(cacheNames=“secondary”, key=“#p0”) })

public Book importBooks(String deposit, Date date)

@CacheConfig

@CacheConfig:缓存提供了许多的注解选项,但是有一些公用的操作,我们可以使用 @CacheConfig 在类上进行全局设置。 以下是个简单的例子:

@CacheConfig(“books”)

public class BookRepositoryImpl implements BookRepository {

@Cacheable

public Book findBook(ISBN isbn) {…}

}

可以共享缓存名称,统一配置 KeyGenerator,CacheManager,CacheResolver。

Redis 整合技巧说明

来看看我们在 springboot 中怎么使用 redis 来作为缓存吧.

cache 配置 redis 作为缓存

pom.xml 引入 redis 依赖

org.springframework.boot

spring-boot-starter-data-redis

 

springboot 集成 redis,文件配置如下:

spring:

redis:

database: 0 # Database index used by the connection factory.

url: redis://user:@127.0.0.1:6379 # Connection URL. Overrides host, port, and password. User is ignored. Example: redis://user:password@example.com:6379

host: 127.0.0.1 # Redis server host.

password: # Login password of the redis server.

port: 6379 # Redis server port.

ssl: false # Whether to enable SSL support.

timeout: 5000 # Connection timeout.

redis 缓存配置类 CacheConfig,这里对 spring 的缓存进行了配置,包括

KeyGenerator

CacheResolver

CacheErrorHandler

CacheManager

还有 redis 序列化方式。

@Configuration

public class CacheConfig extends CachingConfigurerSupport {

//较低版本为2.0.0以下。以上版本Lettuce,但是含义是一样的

@Resource

private RedisConnectionFactory factory;

/**

* 自定义生成redis-key

* @return

*/

@Override

@Bean

public KeyGenerator keyGenerator() {

return (o, method, objects) -> {

StringBuilder sb = new StringBuilder();

sb.append(o.getClass().getName()).append(“.”);

sb.append(method.getName()).append(“.”);

for (Object obj : objects) {

sb.append(obj.toString());

}

return sb.toString();

};

}

@Bean

public RedisTemplate<Object, Object> redisTemplate() {

RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();

redisTemplate.setConnectionFactory(factory);

GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer);

redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);

redisTemplate.setHashKeySerializer(new StringRedisSerializer());

redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);

return redisTemplate;

}

@Bean

@Override

public CacheResolver cacheResolver() {

return new SimpleCacheResolver(cacheManager());

}

// 用于捕获从Cache中进行CRUD时的异常的回调处理器。

@Bean

@Override

public CacheErrorHandler errorHandler() {

return new SimpleCacheErrorHandler();

}

@Bean

@Override

public CacheManager cacheManager() {

RedisCacheConfiguration cacheConfiguration =

defaultCacheConfig()

.disableCachingNullValues()

.serializeValuesWith(RedisSerializationContext

.SerializationPair.fromSerializer(

new GenericJackson2JsonRedisSerializer()));

return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();

}

}

代码使用

测试 @Cacheable 方法

@Test

public void findUserTest() {

for (int i = 0; i < 3; i++) {

System.out.println(“第” + i + “次”);

User user = userService.findUser();

System.out.println(user);

}

}

@Override

@Cacheable(value = {“valueName”, “valueName2”}, key = “‘keyName1’”)

public User findUser() {

System.out.println(“执行方法…”);

return new User(“id1”, “张三”, “深圳”, “1234567”, 18);

}

执行结果

只有一次输出了’执行方法…',后面直接从缓存获取,不会再进入方法。

第0次

执行方法…

User{id=‘id1’, name=‘张三’, address=‘深圳’, tel=‘1234567’, age=18}

第1次

User{id=‘id1’, name=‘张三’, address=‘深圳’, tel=‘1234567’, age=18}

第2次

User{id=‘id1’, name=‘张三’, address=‘深圳’, tel=‘1234567’, age=18}

测试 @CachePut 方法:对缓存进行了修改

@Test

public void updateUserTest() {

userService.updateUser();

User user = userService.findUser();

System.out.println(user);

}

@Override

@CachePut(value = “valueName”, key = “‘keyName1’”)

public User updateUser() {

System.out.println(“更新用户…”);

return new User(“id1”, “李四”, “北京”, “1234567”, 18);

}

执行结果

对缓存进行了更新,获取值的时候取了新的值

更新用户…

User{id=‘id1’, name=‘李四’, address=‘北京’, tel=‘1234567’, age=18}

测试 @CacheEvict 方法:缓存被清空,再次 findUser 的时候又重新执行了方法。

@Test

public void clearUserTest() {

userService.clearUser();

User user = userService.findUser();

System.out.println(user);

}

@Override

@CacheEvict(value = “valueName”,allEntries = true)

public void clearUser() {

System.out.println(“清除缓存…”);

}

执行结果

这里清除了缓存,为什么还是没有执行方法呢?因为这个方法我们定了两个 value 值,清了一个还有一个

清除缓存…

User{id=‘id1’, name=‘张三’, address=‘深圳’, tel=‘1234567’, age=18}

User.java

public class User implements Serializable {

public User() {

}

private String id;

private String name;

private String address;

private String tel;

private Integer age;

//省略get,set,tostring

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

我个人认为,如果你想靠着背面试题来获得心仪的offer,用癞蛤蟆想吃天鹅肉形容完全不过分。想必大家能感受到面试越来越难,想找到心仪的工作也是越来越难,高薪工作羡慕不来,却又对自己目前的薪资不太满意,工作几年甚至连一个应届生的薪资都比不上,终究是错付了,错付了自己没有去提升技术。

这些面试题分享给大家的目的,其实是希望大家通过大厂面试题分析自己的技术栈,给自己梳理一个更加明确的学习方向,当你准备好去面试大厂,你心里有底,大概知道面试官会问多广,多深,避免面试的时候一问三不知。

大家可以把Java基础,JVM,并发编程,MySQL,Redis,Spring,Spring cloud等等做一个知识总结以及延伸,再去进行操作,不然光记是学不会的,这里我也提供一些脑图分享给大家:

希望你看完这篇文章后,不要犹豫,抓紧学习,复习知识,准备在明年的金三银四拿到心仪的offer,加油,打工人!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
些面试题分享给大家的目的,其实是希望大家通过大厂面试题分析自己的技术栈,给自己梳理一个更加明确的学习方向,当你准备好去面试大厂,你心里有底,大概知道面试官会问多广,多深,避免面试的时候一问三不知。

大家可以把Java基础,JVM,并发编程,MySQL,Redis,Spring,Spring cloud等等做一个知识总结以及延伸,再去进行操作,不然光记是学不会的,这里我也提供一些脑图分享给大家:

[外链图片转存中…(img-zWlWiBOa-1713405546232)]

[外链图片转存中…(img-B1Zwiwln-1713405546232)]

[外链图片转存中…(img-n1QgvEDU-1713405546232)]

希望你看完这篇文章后,不要犹豫,抓紧学习,复习知识,准备在明年的金三银四拿到心仪的offer,加油,打工人!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值