缓存方法返回值

1. 业务需求

前端用户查询数据时,数据查询缓慢耗费时间;

基于缓存中间件实现缓存方法返回值:实现流程用户第一次查询时在数据库查询,并将查询的返回值存储在缓存中间件中,在缓存有效期内前端用户再次查询时,从缓存中间件缓存获取

2. 基于Redis实现

参考1

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表达式
相关推荐
醇醛酸醚酮酯3 小时前
多线程是如何保证数据一致和MESI缓存一致性协议
缓存
金心靖晨9 小时前
redis汇总笔记
数据库·redis·笔记
Hello.Reader9 小时前
Redis性能基准测试
数据库·redis·junit
沃夫上校10 小时前
Spring Boot 中使用 Redis
spring boot·redis
鼠鼠我捏,要死了捏11 小时前
基于Redis Streams的实时消息处理实战经验分享
redis·消息队列·redis streams
neoooo12 小时前
Redis锁得住,世界就是你的:一探Redis分布式锁的原理、姿势与深度思考
java·redis·后端
码观天工17 小时前
从 Redis 客户端超时到 .NET 线程池挑战:饥饿、窃取与阻塞的全景解析
redis·线程池·线程饥饿
是2的10次方啊17 小时前
Redis进阶之路:从缓存小白到架构师的完整指南
redis
代码老y19 小时前
穿透、误伤与回环——Redis 缓存防御体系的负向路径与治理艺术
数据库·redis·缓存
Code季风19 小时前
深度优化 spring 性能:从缓存、延迟加载到并发控制的实战指南
java·spring boot·后端·spring·缓存·性能优化