配置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. Kubernetes CKA考试之Killer Simulator(上)

    写在前面 个人微信公众号:密码应用技术实战 个人博客园首页:https://www.cnblogs.com/informatics/ 注:学习交流使用 CKA Simulator Kubernetes ...

  2. 在更新数据的时候,显示一个软件源里面没有Release文件

  3. PagerAdapter深度解析和实践优化

    目录介绍 01.PagerAdapter简单介绍 02.PagerAdapter抽象方法 03.PagerAdapter原理介绍 04.PagerAdapter缓存和销毁 05.自定义PagerAda ...

  4. 【Leetcode】63. 不同路径 II

    题目(链接) 一个机器人位于一个m x n网格的左上角 (起始点在下图中标记为 "Start" ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为 ...

  5. [Python]细节、经验

    [版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://blog.csdn.net/m0_69908381/article/details/132333324 出自[进步* ...

  6. FastWiki(增强AI对话功能)企业级智能客服功能介绍

    知识库对话功能 什么是知识库对话? 我们需要找到AI的知识能力是有限的他们的知识都截止于他们训练数据的时间,你提问他们更新的数据的时候他们就会出现乱回复.而知识库则是利用Prompt给于AI更多的知识 ...

  7. mybatis案例程序

    前置工作 导包(mysql-connector-java.mybatis) 实体类 Mapper层 1.接口 public interface BookMapper { public Book get ...

  8. 前端ajax调用后端下载Excel模板流,解决输出乱码等问题

    JavaScript方法function importTemplate() { $.ajax({ url: "/importTemplate", type: "get&q ...

  9. Python爬取国家统计局2009至2020统计用区划和城乡划分代码(省市区/县三级)并存入mysql数据库

    国家统计局->统计标准网址:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/ 获取资源请关注公众号 [靠谱杨阅读人生]回复[城乡分类]获取 流程 ...

  10. sql语句TRUNCATE 清空表数据

    清空表数据 TRUNCATE TABLE zzsfp_hwmx;