1. 业务需求
前端用户查询数据时,数据查询缓慢耗费时间;
基于缓存中间件实现缓存方法返回值:实现流程用户第一次查询时在数据库查询,并将查询的返回值存储在缓存中间件中,在缓存有效期内前端用户再次查询时,从缓存中间件缓存获取
2. 基于Redis实现
2.1 简单实现
引入cache依赖
java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
在redis配置类中添加cache缓存机制
java
/**
* redis配置
*
* @author ruoyi
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
/**
* 方法返回值缓存策略
*
* @param factory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(2 * 60))//过期超时时间 2分钟
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware()
.build();
}
//......其他配置不展示.....
}
启动类开始方法缓存@EnableCaching
java
package com.ruoyi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
/**
* 启动程序
*
* @author ruoyi
*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableCaching
public class RuoYiApplication
{
public static void main(String[] args)
{
// System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}
业务层设置缓存方法
java
@Override
@Cacheable(cacheNames = "selectuserlist",key = "#user.userId")
public List<SysUser> selectUserList(SysUser user)
{
return userMapper.selectUserList(user);
}
测试效果
第一次请求时
第二次请求时,没有查询数据库
查询userId为2的用户
两分钟过后
2.2 设置自定义过期时长
创建RedisCache解析器
java
package com.ruoyi.framework.config.properties;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import java.time.Duration;
/**
* RedisCache解析器
*/
public class MyRedisCacheManager extends RedisCacheManager {
public MyRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
super(cacheWriter, defaultCacheConfiguration);
}
@Override
protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
//解析name字段
if (!StringUtils.isEmpty(name) && name.contains("#")) {
//获取时间
String numStr = name.split("#")[1];
if (StringUtils.isNumeric(numStr)) {
//重置缓存时长
return super.createRedisCache(name, cacheConfig.entryTtl(Duration.ofSeconds(Integer.parseInt(numStr))));
}
}
return super.createRedisCache(name, cacheConfig);
}
}
配置RedisConfig
java
package com.ruoyi.framework.config;
import com.ruoyi.framework.config.properties.MyRedisCacheManager;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* redis配置
*
* @author ruoyi
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
/**
* 方法返回值缓存策略
*
* @param factory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(2 * 60))//过期超时时间 2分钟
.disableCachingNullValues();
// return RedisCacheManager.builder(factory)
// .cacheDefaults(config)
// .transactionAware()
// .build();
return new MyRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(factory), config);
}
//...............其他配置...略..........
}
使用160秒有效
java
@Override
@Cacheable(cacheNames = "selectuserlist#160",key = "#user.userId")
public List<SysUser> selectUserList(SysUser user)
{
return userMapper.selectUserList(user);
}
2.3 注解Cacheable.key
- 声明访问缓存的键,由于缓存本质上是键值存储,因此每次调用缓存方法时都需要使用键去访问。
- 缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。这个 key 可以使用 spEL 表达式来编写。
- 这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用"#参数名"或者"#p参数index"。
java
@Cacheable(cacheNames="books", key="#isbn")
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="#p0")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(cacheNames="books", key="#p0.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
- spEL表达式