1. 业务需求
前端用户查询数据时,数据查询缓慢耗费时间;
基于缓存中间件实现缓存方法返回值:实现流程用户第一次查询时在数据库查询,并将查询的返回值存储在缓存中间件中,在缓存有效期内前端用户再次查询时,从缓存中间件缓存获取
2. 基于Redis实现
参考1
2.1 简单实现
引入cache依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency>
在redis配置类中添加cache缓存机制
/*** redis配置** @author ruoyi*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {/*** 方法返回值缓存策略** @param factory* @return*/@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(2 * 60))//过期超时时间 2分钟.disableCachingNullValues();return RedisCacheManager.builder(factory).cacheDefaults(config).transactionAware().build();}//......其他配置不展示.....
}
启动类开始方法缓存@EnableCaching
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" +" ''-' `'-' `-..-' ");}
}
业务层设置缓存方法
@Override@Cacheable(cacheNames = "selectuserlist",key = "#user.userId")public List<SysUser> selectUserList(SysUser user){return userMapper.selectUserList(user);}
测试效果
第一次请求时
第二次请求时,没有查询数据库
查询userId为2的用户
两分钟过后
2.2 设置自定义过期时长
创建RedisCache解析器
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);}@Overrideprotected 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
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*/@Beanpublic 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秒有效
@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”。
@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表达式