配置Spring Cache

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>1.16</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
</dependency>
spring:
cache:
type: redis
### 配置Redis
# Redis数据库索引(默认为0)
redis:
database: 0
# Redis服务器地址
host: mmren.edu.redis.server
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
password: ENC(bIx3PYzFf0CcZ+6CdAGHruIaTgY1/CyB)
# 配置连接池
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 500
# 连接池中的最小空闲连接
min-idle: 0
# 连接超时时间(毫秒)
timeout: 2000
lettuce:
shutdown-timeout: 0
jasypt:
encryptor:
password: gerrymmrenedu # 设置根密码

缓存配置类

@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport { @Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
// 创建Redis序列化对象
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
// 使用Jackson的序列化对象
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om); // 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
// 7 天缓存过期
.entryTtl(Duration.ofDays(7))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build(); return cacheManager;
}
}

创建实体

public class Book implements Serializable {
private static final long serialVersionUID = 2629983876059197650L; private String id;
private String name; // 书名
private Integer price; // 价格
private Date update; // public Book(String id, String name, Integer price, Date update) {
super();
this.id = id;
this.name = name;
this.price = price;
this.update = update;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Date getUpdate() {
return update;
}
public void setUpdate(Date update) {
this.update = update;
}
}
--------------------------------
public class BookQry {
private String id;
private String name; // 书名
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} @Override
public String toString(){
return JSON.toJSONString(this);
}
}

数据初始化类

public abstract class AbstractService {

    protected static Map<String, Book> repositoryBook = new HashMap<>();
public AbstractService() {
super();
} @PostConstruct
public void init() {
// 1
Book book1 = new Book("1001", "牧码人", 11, new Date());
repositoryBook.put(book1.getId(), book1);
// 2
Book book2 = new Book("1002", "张三", 43, new Date());
repositoryBook.put(book2.getId(), book2);
// 3
Book book3 = new Book("1003", "Gerry", 5433, new Date());
repositoryBook.put(book3.getId(), book3);
// 4
Book book4 = new Book("1004", "教育", 54, new Date());
repositoryBook.put(book4.getId(), book4);
}
}

自定义缓存key生成类

@Component
public class MyKeyGenerator implements KeyGenerator { @Override
public Object generate(Object target, Method method, Object... params) {
System.out.println("自定义缓存,使用第一参数作为缓存key. params = " + Arrays.toString(params));
// 仅仅用于测试,实际不可能这么写
return params[0] + "0";
} }

Spring缓存的基本用法

@Component
public class BookService extends AbstractService {
private static final Logger logger = LoggerFactory.getLogger(BookService.class); // ==================== @Cacheable ========================
/**
* cacheNames 设置缓存的值
* key:指定缓存的key,这是指参数id值。 key可以使用spEl表达式
* @param id
* @return
*/
@Cacheable(cacheNames="book1", key="#id")
public Book queryBookCacheable(String id){
logger.info("queryBookCacheable,id={}",id);
return repositoryBook.get(id);
} /**
* 这里使用另一个缓存存储缓存
*
* @param id
* @return
*/
@Cacheable(cacheNames="book2", key="#id")
public Book queryBookCacheable_2(String id){
logger.info("queryBookCacheable_2,id={}",id);
return repositoryBook.get(id);
} /**
* 缓存的key也可以指定对象的成员变量
* @param qry
* @return
*/
@Cacheable(cacheNames="book1", key="#qry.id")
public Book queryBookCacheableByBookQry(BookQry qry){
logger.info("queryBookCacheableByBookQry,qry={}",qry);
String id = qry.getId();
Assert.notNull(id, "id can't be null!");
String name = qry.getName();
Book book = null;
if(id != null){
book = repositoryBook.get(id);
if(book != null && !(name != null && book.getName().equals(name))){
book = null;
}
}
return book;
} /**
* 以上我们使用默认的keyGenerator,对应spring的SimpleKeyGenerator
* 如果你的使用很复杂,我们也可以自定义myKeyGenerator的生成key
*
* key和keyGenerator是互斥,如果同时制定会出异常
* The key and keyGenerator parameters are mutually exclusive and an operation specifying both will result in an exception.
*
* @param id
* @return
*/
@Cacheable(cacheNames="book3", keyGenerator="myKeyGenerator")
public Book queryBookCacheableUseMyKeyGenerator(String id){
logger.info("queryBookCacheableUseMyKeyGenerator,id={}",id);
return repositoryBook.get(id);
} /***
* 如果设置sync=true,
* 如果缓存中没有数据,多个线程同时访问这个方法,则只有一个方法会执行到方法,其它方法需要等待
* 如果缓存中已经有数据,则多个线程可以同时从缓存中获取数据
* @param id
* @return
*/
@Cacheable(cacheNames="book3", sync=true)
public Book queryBookCacheableWithSync(String id) {
logger.info("begin ... queryBookCacheableByBookQry,id={}",id);
try {
Thread.sleep(1000 * 2);
} catch (InterruptedException e) {
}
logger.info("end ... queryBookCacheableByBookQry,id={}",id);
return repositoryBook.get(id);
} /**
* 条件缓存:
* 只有满足condition的请求才可以进行缓存,如果不满足条件,则跟方法没有@Cacheable注解的方法一样
* 如下面只有id < 3才进行缓存
*
*/
@Cacheable(cacheNames="book11", condition="T(java.lang.Integer).parseInt(#id) < 3 ")
public Book queryBookCacheableWithCondition(String id) {
logger.info("queryBookCacheableByBookQry,id={}",id);
return repositoryBook.get(id);
} /**
* 条件缓存:
* 对不满足unless的记录,才进行缓存
* "unless expressions" are evaluated after the method has been called
* 如下面:只对不满足返回 'T(java.lang.Integer).parseInt(#result.id) <3 ' 的记录进行缓存
* @param id
* @return
*/
@Cacheable(cacheNames="book22", unless = "T(java.lang.Integer).parseInt(#result.id) <3 ")
public Book queryBookCacheableWithUnless(String id) {
logger.info("queryBookCacheableByBookQry,id={}",id);
return repositoryBook.get(id);
} // ==================== @CacheEvict ========================
/**
* allEntries = true: 清空book1里的所有缓存
*/
@CacheEvict(cacheNames="book1", allEntries=true)
public void clearBook1All(){
logger.info("clearAll");
}
/**
* 对符合key条件的记录从缓存中book1移除
*/
@CacheEvict(cacheNames="book1", key="#id")
public void updateBook(String id, String name){
logger.info("updateBook");
Book book = repositoryBook.get(id);
if(book != null){
book.setName(name);
book.setUpdate(new Date());
}
} // ==================== @CachePut ========================
/**
* 每次执行都会执行方法,无论缓存里是否有值,同时使用新的返回值的替换缓存中的值
* 这里不同于@Cacheable:@Cacheable如果缓存没有值,从则执行方法并缓存数据,如果缓存有值,则从缓存中获取值
* @param id
* @return
*/
@CachePut(cacheNames="book1", key="#id")
public Book queryBookCachePut(String id){
logger.info("queryBookCachePut,id={}",id);
return repositoryBook.get(id);
} }

@CacheConfig配置定义

/**
* @CacheConfig: 类级别的注解
* 如果我们在此注解中定义cacheNames,则此类中的所有方法上@Cacheable的cacheNames默认都是此值。当然 * @Cacheable也可以重定义cacheNames的值
*
*/
@Component
@CacheConfig(cacheNames="booksAll")
public class BookService2 extends AbstractService {
private static final Logger logger = LoggerFactory.getLogger(BookService2.class); /**
* 此方法的@Cacheable没有定义cacheNames,则使用类上的注解@CacheConfig里的值 cacheNames
* @param id
* @return
*/
@Cacheable(key="#id")
public Book queryBookCacheable(String id){
logger.info("queryBookCacheable,id={}",id);
return repositoryBook.get(id);
} /**
* 此方法的@Cacheable有定义cacheNames,则使用此值覆盖类注解@CacheConfig里的值cacheNames
*
* @param id
* @return
*/
@Cacheable(cacheNames="books_custom", key="#id")
public Book queryBookCacheable2(String id){
logger.info("queryBookCacheable2,id={}",id);
return repositoryBook.get(id);
}
}

编写测试用例

public class RedisCacheTests  extends  ApplicationTests{
@Autowired
private BookService bookService; @Test
public void testCache1() throws Exception {
Book book = bookService.queryBookCacheable("1001");
convertToString(book);
} @Test
public void testCache2() throws Exception {
Book book = bookService.queryBookCacheable_2("1001");
convertToString(book);
} @Test
public void testCache3() throws Exception {
BookQry qry = new BookQry();
qry.setId("1004");
qry.setName("教育");
Book book = bookService.queryBookCacheableByBookQry(qry);
convertToString(book);
} @Test
public void testCache4() throws Exception {
Book book = bookService.queryBookCacheableUseMyKeyGenerator("1003");
convertToString(book);
} @Test
public void testCache5() throws Exception {
Book book = bookService.queryBookCachePut("1003");
convertToString(book);
} public void convertToString(Object object) {
String jsonString = JSON.toJSONString(object, true);
System.out.println(jsonString);
}
}

SpringBoot使用Redis做缓存结合自带注解的更多相关文章

  1. springboot中redis做缓存时的配置

    import com.google.common.collect.ImmutableMap;import org.slf4j.Logger;import org.slf4j.LoggerFactory ...

  2. springboot利用redis做缓存

    首先 配置redis redis: password: 123456 host: 127.0.0.1 port: 6379 #103.249.252.109:10086 expireSeconds: ...

  3. spring-boot集成mybatis,用redis做缓存

    网上有很多例子了,执行源码起码有3个,都是各种各样的小问题. 现在做了个小demo,实现spring-boot 用redis做缓存的实例,简单记录下思路,分享下源码. 缓存的实现,分担了数据库的压力, ...

  4. SpringBoot之Mybatis操作中使用Redis做缓存

    上一博客学习了SpringBoot集成Redis,今天这篇博客学习下Mybatis操作中使用Redis做缓存.这里其实主要学习几个注解:@CachePut.@Cacheable.@CacheEvict ...

  5. 如何使用Redis做缓存

    如何使用Redis做缓存 我们都知道Redis作为NoSql数据库的代表之一,通常会用来作为缓存使用.也是我在工作中通常使用的缓存之一. 1.我们什么时候缓存需要用到Redis? 我认为,缓存可以分为 ...

  6. springboot2.0+redis实现消息队列+redis做缓存+mysql

    本博客仅供参考,本人实现没有问题. 1.环境 先安装redis.mysql 2.springboot2.0的项目搭建(请自行完成),本人是maven项目,因此只需配置,获取相应的jar包,配置贴出. ...

  7. spring+redis的集成,redis做缓存

    1.前言 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.我们都知道,在日常的应用中,数据库瓶颈是最容易出现的 ...

  8. django使用redis做缓存

    Django 使用 Redis 做缓存 django中应用redis:pip3 install django-redis - 配置 CACHES = { "default": { ...

  9. Spring Boot 2整合Redis做缓存

    既然是要用Redis做缓存,自然少不了安装了.但是本文主要讲Spring Boot与Redis整合.安装教程请另行百度! 1.首先是我们的Redis配置类 package com.tyc; impor ...

  10. 如何用redis做缓存

    redis缓存 在互联网应用中经常需要用redis来缓存热点数据. redis数据在内存,可以保证数据读取的高效,接近每秒数十万次的吞吐量 减少下层持久层数据库读取压力,像mongodb,每秒近千次读 ...

随机推荐

  1. Python面向对象之派生和组合

    [一]什么是派生 派生是指,子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法 [二]派生的方法 子类可以派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找 例如每个老 ...

  2. 别名路径跳转 - vscode 插件

    别名路径跳转 - vscode 插件

  3. Linux常用指令2

    1.系统常用命令 1)在文件中查找内容 grep >grep  hello passwd //在passwd文件中搜索hello内容,会把hello所在行的内容打印到终端显示 2)查看系统中活跃 ...

  4. 建民哥哥的AV

    1 #include<bits/stdc++.h> 2 #include<vector> 3 #include<algorithm> 4 using namespa ...

  5. python面向对象编程(封装、隐藏)

    一 封装 1.封装介绍封装是面向对象三大特性最核心的一个特性封装<----->整合2.将封装的属性进行隐藏操作1).如何隐藏:在属性名前加__前缀,就会实现一个对外隐藏属性效果该隐藏需要注 ...

  6. Python 如何通过网易163邮箱自动发送邮件

    一.发送邮件的前提是必须开通发件服务器获取对应授权密码. 二.对应代码如下所示 import smtplib from email.mime.text import MIMEText from ema ...

  7. Linux开发相关命令整理

    1. 反转shell 2. ldd 3. objdump 4. ldconfig 5. telnet 6. nc 7. netstat 8. ss 9. tcpdump 10. lsof 11. st ...

  8. 'scanf': This function or variable may be unsafe

    'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable depreca ...

  9. #排列组合,背包#CF232B Table

    题目 有一个 \(n\times m\) 的矩阵,求使得每个 \(n\times n\) 的矩阵中都有正好 \(k\) 个点的方案数. 分析 考虑到如果确定了前 \(n\) 列的选点个数,那么对于一列 ...

  10. C++ While 和 For 循环:流程控制全解析

    C++ Switch 语句 使用 switch 语句选择要执行的多个代码块之一. 语法 switch(expression) { case x: // 代码块 break; case y: // 代码 ...