SpringBoot集成Redis作数据缓存-阿里云开发者社区

开发者社区> 三分恶> 正文

SpringBoot集成Redis作数据缓存

简介: SpringBoot集成Redis作数据缓存
+关注继续查看


@[Toc]


一、缓存简介

Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 Redis),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。

目前 Spring Boot 支持的缓存有如下几种:

  • JCache (JSR-107)
  • EhCache 2.x
  • Hazelcast
  • lnfinispan
  • Couchbase
  • Redis
  • Caffeine
  • Simple

目前常用的缓存实现 Ehcache 2.x和 Redis。由于 Spring 早己将缓存领域统一 ,因此无论使用哪种缓存实现,不同的只是缓存配置,开发者使用的缓存注解是一致的( Spring 缓存注解和各缓存实现的关系就像 JDBC和各种数据库驱动的关系)。

这里学习使用Redis作为缓存实现。


二、Redis缓存


1、添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>


2、属性配置

在application.properties中添加配置:

spring.redis.host=localhost
spring.redis.password=
# 一般来说是不用配置的,Spring Cache 会根据依赖的包自行装配
spring.cache.type=redis
# 连接超时时间(毫秒)
spring.redis.timeout=10000
# Redis默认情况下有16个分片,这里配置具体使用的分片
spring.redis.database=0
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0


3、 Cache核心注解


spring-boot-starter-cache 是 Spring Boot 体系内提供使⽤ Spring Cache的Starter 包。其中最核⼼的三个注解:@Cacheable、@CacheEvict、@CachePut。

3.1、@Cacheable

@Cacheable⽤来声明⽅法是可缓存的,将结果存储到缓存中以便后续使⽤相同参数调⽤时不需执⾏实际的⽅法,直接从缓存中取值。@Cacheable 可以标记在⼀个⽅法上,也可以标记在⼀个类上。当标记在⼀个⽅法上时表示该⽅法是⽀持缓存的,当标记在⼀个类上时则表示该类所有的⽅法都是⽀持缓存的。

例如:

@RequestMapping("/hello")
@Cacheable(value="helloCache")
public String hello(String name) {
 System.out.println("没有⾛缓存!");
 return "hello "+name;
}

@Cacheable ⽀持如下⼏个参数。

  • value:缓存的名称。
  • key:缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写;如果不指定,则缺省按照⽅法的所有参数进⾏组合。
  • condition:触发条件,只有满⾜条件的情况才会加⼊缓存,默认为空,既表示全部都加⼊缓存,⽀持SpEL。

把上⾯的⽅法稍微更改:

@RequestMapping("/condition")
@Cacheable(value="condition",condition="#name.length() <= 4")
public String condition(String name) {
 System.out.println("没有⾛缓存!");
 return "hello "+name;
}


3.2、@CachePut

项⽬运⾏中会对数据库的信息进⾏更新,如果仍然使⽤ @Cacheable 就会导致数据库的信息和缓存的信息不⼀致。在以往的项⽬中,⼀般更新完数据库后,再⼿动删除掉 Redis 中对应的缓存,以保证数据的⼀致性。Spring 提供了另外的⼀种解决⽅案,可以以优雅的⽅式去更新缓存。

与 @Cacheable 不同的是使⽤ @CachePut 标注的⽅法在执⾏前,不会去检查缓存中是否存在之前执⾏过的结果,⽽是每次都会执⾏该⽅法,并将执⾏结果以键值对的形式存⼊指定的缓存中。

@CachePut 配置⽅法:

  • value 缓存的名称。
  • key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照⽅法的所有参数进⾏组合。
  • condition 缓存的条件,可以为空,使⽤ SpEL 编写,返回 true 或者 false,只有为 true 才进⾏缓存。


3.3、@CacheEvict

@CacheEvict 是⽤来标注在需要清除缓存元素的⽅法或类上的,当标记在⼀个类上时表示其中所有的⽅法的执⾏都会触发缓存的清除操作。@CacheEvict 可以指定的属性有 value、key、condition、allEntries 和beforeInvocation,其中 value、key 和 condition 的语义与 @Cacheable 对应的属性类似。即 value 表示清除操作是发⽣在哪些 Cache 上的(对应 Cache 的名称);key 表示需要清除的是哪个 key,如未指定则会使⽤默认策略⽣成的 key;condition 表示清除操作发⽣的条件。


3.4、总结

  • @Cacheable 作⽤和配置⽅法

主要针对⽅法配置,能够根据⽅法的请求参数对其结果进⾏缓存:

主要参数解 释举例
value缓存的名称,在 spring 配置⽂件中定义,必须指定⾄少⼀个如 @Cacheable(value="mycache")或者 @Cacheable(value={"cache1","cache2"}
key缓存的 key,可以为空,如果指定要按照 SpEL表达式编写,如果不指定,则缺省按照⽅法的所有参数进⾏组合如@Cacheable(value="testcache",key="#userName")
condition缓存的条件,可以为空,使⽤ SpEL 编写,返回true 或者 false,只有为 true 才进⾏缓存如@Cacheable(value="testcache",condition="#userName.length()>2")


  • @CachePut 作⽤和配置⽅法

@CachePut 的作⽤是主要针对⽅法配置,能够根据⽅法的请求参数对其结果进⾏缓存,和 @Cacheable 不同的是,它每次都会触发真实⽅法的调⽤。

主要参数解释举例
value缓存的名称,在 spring 配置⽂件中定义,必须指定⾄少⼀个如@Cacheable(value="mycache")或者 @Cacheable(value={"cache1","cache2"}
key缓存的 key,可以为空,如果指定要按照 SpEL表达式编写,如果不指定,则缺省按照⽅法的所有参数进⾏组合如@Cacheable(value="testcache",key="#userName")
condition缓存的条件,可以为空,使⽤ SpEL 编写,返回true 或者 false,只有为 true 才进⾏缓存如@Cacheable(value="testcache",condition="#userName.length()>2")


  • @CacheEvict 作⽤和配置⽅法

主要针对⽅法配置,能够根据⼀定的条件对缓存进⾏清空。

主要参数解释举例
value缓存的名称,在 spring 配置⽂件中定义,必须指定⾄少⼀个如 @CachEvict(value="mycache")或者 @CachEvict(value={"cache1","cache2"}
key缓存的 key,可以为空,如果指定要按照SpEL 表达式编写,如果不指定,则缺省按照⽅法的所有参数进⾏组合如@CachEvict(value="testcache",key="#userName")
condition缓存的条件,可以为空,使⽤ SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存如@CachEvict(value="testcache",condition="#userName.length()>2")
allEntries是否清空所有缓存内容,缺省为 false,如果指定为 true,则⽅法调⽤后将⽴即清空所有缓存如@CachEvict(value="testcache",allEntries=true)
beforeInvocation是否在⽅法执⾏前就清空,缺省为 false,如果指定为 true,则在⽅法还没有执⾏的时候就清空缓存,缺省情况下,如果⽅法执⾏抛出异常,则不会清空缓存如@CachEvict(value="testcache",beforeInvocation=true)


4、Cache具体使用

4.1、实体类

定义一个User类,模拟对象存储:

public class User implements Serializable {
    private static final long serialVersionUID = 8655851615465363473L;
    private Long id;
    private String username;
    private String password;
    
    //省略getter、setter
}       


4.2、服务层


  • 接口:
public interface UserService {

    /**
     * 删除
     *
     * @param user 用户对象
     * @return 操作结果
     */
    User saveOrUpdate(User user);

    /**
     * 添加
     *
     * @param id key值
     * @return 返回结果
     */
    User get(Long id);

    /**
     * 删除
     *
     * @param id key值
     */
    void delete(Long id);
}


  • 实现类:

实现类里用到了最核心的三个注解:@Cacheable、@CachePut、@CacheEvict

@Service
public class UserServiceImpl implements UserService {
    private static final Map<Long, User> DATABASES = new HashMap<>();

    static {
        DATABASES.put(1L, new User(1L, "u1", "p1"));
        DATABASES.put(2L, new User(2L, "u2", "p2"));
        DATABASES.put(3L, new User(3L, "u3", "p3"));
    }


    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Cacheable(value = "user", key = "#id")
    @Override
    public User get(Long id) {
        // TODO 假设它是从数据库读取出来的
        log.info("进入 get 方法");
        return DATABASES.get(id);
    }

    @CachePut(value = "user", key = "#user.id")
    @Override
    public User saveOrUpdate(User user) {
        DATABASES.put(user.getId(), user);
        log.info("进入 saveOrUpdate 方法");
        return user;
    }

    @CacheEvict(value = "user", key = "#id")
    @Override
    public void delete(Long id) {
        DATABASES.remove(id);
        log.info("进入 delete 方法");
    }
}


4.4、启动类

启动类需要开启缓存配置@EnableCaching

@SpringBootApplication
@EnableCaching
public class SpringbootCacheRedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootCacheRedisApplication.class, args);
    }

}


4.5、测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class CacheRedisTest {

    private static final Logger log = LoggerFactory.getLogger(CacheRedisTest.class);


    @Autowired
    private UserService userService;


    @Test
    public void get() {
        final User user = userService.saveOrUpdate(new User(5L, "u5", "p5"));
        log.info("[saveOrUpdate] - [{}]", user);
        final User user1 = userService.get(5L);
        log.info("[get] - [{}]", user1);
        userService.delete(5L);
    }
}

运行结果:

在这里插入图片描述可以看到增删改查中,查询是没有日志输出的,因为它直接从缓存中获取的数据,而添加、修改、删除都是会进入方法内执行具体的业务代码,然后通过切面去删除掉Redis中的缓存数据。



参考:

【1】:《精通 Spring Boot 42 讲》
【2】:一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
【3】:《Spring Boot Vue全栈开发实战》
【4】:Spring Cache + Redis

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
SpringBoot基于数据库实现简单的分布式锁
本文介绍SpringBoot基于数据库实现简单的分布式锁
1346 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
8886 0
【springboot+easypoi】大数据量excel导出
上次写了一行代码解决导出导入,没看的小伙伴建议先看下《【springboot+easypoi】一行代码搞定excel导入导出》,但是实际业务中遇到一个问题,如果数据里比较大的时候,例如10w+数据一次导出,就会出现卡死情况,继续看官方文档,有大数据量...
2856 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10667 0
SpringBoot如何使用JPA操作数据库?
介绍如何在SpringBoot中使用JPA,并介绍JPA的相关知识点和原理
2933 0
第十二篇:SpringBoot 2.x数据校验
介绍 在项目的过程中,对于参数的校验是必须的,如果参数比较少的话我们可以直接通过代码进行校验,但是数据较大时再用这个方法就比较笨重了,接下来就该我们的主角Validation闪亮登场了 pom.
1780 0
SpringBoot实战(四)之使用JDBC和Spring访问数据库
这里演示的是h2databse示例,所以简单的介绍普及下h2database相关知识 H2数据库是一个开源的关系型数据库。 H2是一个嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2提供了一个十分方便的web控制台用于操作和管理数据库内容。
2214 0
spring + redis 实现数据的缓存
1、实现目标   通过redis缓存数据。(目的不是加快查询的速度,而是减少数据库的负担)   2、所需jar包      注意:jdies和commons-pool两个jar的版本是有对应关系的,注意引入jar包是要配对使用,否则将会报错。
503 0
+关注
三分恶
一个能文能武的全栈开发~
340
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载