Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringBoot使用Redis做缓存结合自带注解

SpringBoot使用Redis做缓存结合自带注解

作者头像
HUC思梦
发布于 2020-09-03 09:17:09
发布于 2020-09-03 09:17:09
1.6K00
代码可运行
举报
运行总次数:0
代码可运行
配置Spring Cache
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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>
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring:
  cache:
    type: redis
    ### 配置Redis
    # Redis数据库索引(默认为0redis:
      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 # 设置根密码
缓存配置类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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;
    }
}
创建实体
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
    }
}
数据初始化类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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生成类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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缓存的基本用法
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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配置定义
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @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);
    }
}
编写测试用例
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-04-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
补习系列(14)-springboot 之 redis 读写秘技
在 补习系列(A3)-springboot redis 与发布订阅 一文中,我们介绍了使用 Redis 实现消息订阅发布的机制,并且给出了一个真实用例。
美码师
2019/01/23
6600
SpringBoot Redis 2.0.x
在笔者之前的文章中有介绍redis的安装,不会的可以去看 笔者之前写的文章redis安装
tanoak
2018/07/13
4010
SpringBoot Redis 2.0.x
SpringBoot系列-- 集成 Redis 缓存(实战)
通过控制台输出信息我们可以知道,这次执行了数据库查询,并开启了Redis缓存查询结果。接下来我们再次查询user表中id=24的数据,观察控制台,如下:
田维常
2020/02/13
2.1K0
SpringBoot系列-- 集成 Redis 缓存(实战)
Spring Cache+Redis缓存数据
  我们知道内存的读取速度远大于硬盘的读取速度。当需要重复地获取相同数据时,一次一次地请求数据库或者远程服务,导致在数据库查询或远程方法调用上消耗大量的时间,最终导致程序性能降低,这就是数据缓存要解决的问题。
别团等shy哥发育
2023/02/25
1.1K0
Spring Cache+Redis缓存数据
spring boot 集成redis版本说明
官网文档:https://docs.spring.io/spring-boot/docs/2.0.2.RELEASE/reference/htmlsingle/
全栈程序员站长
2022/07/28
1.6K0
Spring cache 使用Redis做分布式缓存
DemoApplication启动类头部加入@EnableCaching开启缓存 redis.config配置
阿提说说
2022/12/02
6130
重学SpringBoot系列之Spring cache详解
使用缓存是一个很“高性价比”的性能优化方式,尤其是对于有大量重复查询的程序来说。通常来说,在WEB后端应用程序来说,耗时比较大的往往有两个地方:一个是查数据库,一个是调用其它服务的API(因为其它服务最终也要去做查数据库等耗时操作)。
大忽悠爱学习
2021/12/07
1.7K0
重学SpringBoot系列之Spring cache详解
0x02 SpringBoot使用注解方式同时集成Redis、Ehcache
链接:https://pan.baidu.com/s/1xZqpQQOcVgkr0W_FrItHRw 密码:x2jo
上善若水.夏
2018/09/28
2.8K0
SpringBoot缓存注解@Cacheable之自定义key策略及缓存失效时间指定
上一篇博文介绍了Spring中缓存注解@Cacheable @CacheEvit @CachePut的基本使用,接下来我们将看一下更高级一点的知识点
一灰灰blog
2021/07/02
8.8K0
SpringBoot缓存注解@Cacheable之自定义key策略及缓存失效时间指定
SpringBoot Cache 入门
@CacheEvict(cacheNames = "tea",key = "#id")
tanoak
2018/07/13
6310
SpringBoot Cache 入门
(11)SpringBoot整合EhCache做缓存
EhCache 简介:EhCache 是一个纯Java的进程内缓存框架,是Hibernate中默认的CacheProvider;其缓存的数据可以存放在内存里面,也可以存放在硬盘上;其核心是CacheManager,一切Ehcache的应用都是从CacheManager开始的;它是用来管理Cache(缓存)的,一个应用可以有多个CacheManager,而一个CacheManager下又可以有多个Cache;Cache内部保存的是一个个的Element,而一个Element中保存的是一个key和value的配对,相当于Map里面的一个Entry。
IT云清
2022/05/07
1.3K0
微服务架构Day09-SpringBoot之缓存
Java Caching定义5个核心接口:CachingProvider,CacheManager,Cache,Entry,Expiry
攻城狮Chova
2022/01/22
3820
整合@Cache 和 Redis
顾名思义,@Cacheable可以用来进行缓存的写入,将结果存储在缓存中,以便于在后续调用的时候可以直接返回缓存中的值,而不必再执行实际的方法。最简单的使用方式,注解名称=缓存名称,使用例子如下:
BUG弄潮儿
2021/10/08
7740
整合@Cache 和 Redis
spring-boot-2.0.3之redis缓存实现,不是你想的那样哦!
    小白问小明:“你前面有一个5米深的坑,里面没有水,如果你跳进去后该怎样出来了?”小明:“躺着出来呗,还能怎么出来?”小白:“为什么躺着出来?”小明:“5米深的坑,还没有水,跳下去不死就很幸运了,残是肯定会残的,不躺着出来,那能怎么出来?”小白:“假设没死也没残呢?”小明:“你当我超人了? 那也简单,把脑子里的水放出来就可以漂出来了。”小白:“你脑子里有这么多水吗?”小明:“我脑子里没那么多水我跳下去干嘛?” 
青石路
2018/12/06
2.6K0
spring-boot-2.0.3之redis缓存实现,不是你想的那样哦!
springboot整合redis
springboot通常整合redis,采用的是RedisTemplate的形式,除了这种形式以外,还有另外一种形式去整合,即采用spring支持的注解进行访问缓存 。
BUG弄潮儿
2022/06/30
5390
springboot使用cache缓存
Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支持使用JCache(JSR-107)注解简化我们开发;
吟风者
2019/07/25
1K0
springBoot高级
1、在springBoot中可以使用注解式开发缓存,默认没有开启缓存中间件,那么使用的就是存储在Map中的原理,但是我们还可以配置自己的缓存中间件,比如redis
爱撒谎的男孩
2019/12/31
6750
你知道如何在springboot中使用redis吗
特别说明:本文针对的是新版 spring boot 2.1.3,其 spring data 依赖为 spring-boot-starter-data-redis,且其默认连接池为 lettuce
用户2038589
2019/06/02
1.3K0
Spring学习笔记(三十二)——SpringBoot中cache缓存的介绍和使用
cache 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。
不愿意做鱼的小鲸鱼
2022/09/26
2.7K0
Spring学习笔记(三十二)——SpringBoot中cache缓存的介绍和使用
springBoot 缓存开发
package catchManager; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; /**
用户5927264
2019/08/01
4070
相关推荐
补习系列(14)-springboot 之 redis 读写秘技
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验