Spring 框架入门教程
1. 1. Spring 框架 2. 2. Spring 5 3. 3. Spring WebFlux 4. 4. 先介绍一下 Spring 5. 5. 什么是 Spring 依赖注入 6. 6. 什么是 Spring IoC 容器 和 Bean 7. 7. Spring Bean 的生命周期 8. 8. Spring REST 开发 9. 9. Spring REST XML 10. 10. Spring RestTemplate 开发 11. 11. Spring AOP 切面编程 12. 12. Spring AOP 方法调优 13. 13. Spring 注解详解 14. 14. Spring 核心注解之 @Autowired 15. 15. Spring 核心注解之 @RequestMapping 16. 16. Spring MVC 开发样例 17. 17. Spring MVC 开发指南 18. 18. Spring MVC 异常处理机制 19. 19. Spring MVC Validator 20. 20. Spring MVC 拦截器 21. 21. Spring MVC 文件上传 22. 22. Spring MVC 国际化(i18n) 23. 23. Spring MVC Hibernate MqSQL 24. 24. Spring ORM 25. 25. Spring ORM JPA 26. 26. Spring Data JPA 27. 27. Spring 事务管理 28. 28. 常用的 Spring JdbcTemplate 29. 29. Spring Security 简介 30. 30. Spring Security 教程 31. 31. Spring Security UserDetailsService 32. 32. Spring MVC 登录注销简单案例 33. 33. Spring Security Roles 34. 34. Spring Boot Tutorial 35. 35. Spring Boot Components 36. 36. Spring Boot CLI Hello World 37. 37. Spring Boot Initilizr Web 38. 38. Spring Boot Initilizr IDE 39. 39. Spring Boot Initilizr CLI 40. 40. Spring Boot Initilizr Tools 41. 41. Spring Boot MongoDB 42. 42. Spring Boot Redis Cache 43. 43. Spring Boot 常见面试问题 44. 44. Spring Batch 45. 45. Spring Batch 批处理示例 46. 46. Spring AMQP 47. 47. Spring RabbitMQ 48. 48. Spring AMQP RabbitMQ 49. 49. Apache ActiveMQ 安装与启动 50. 50. Spring ActiveMQ 教程 51. 51. Spring ActiveMQ 示例 52. 52. Spring JDBC 53. 53. Spring DataSource JNDI 54. 54. Spring Hibernate 55. 55. Spring Primefaces JPA 56. 56. Spring Primefaces MongoDB 57. 57. Spring Primefaces Hibernate 58. 58. SpringRoo Primefaces Hibernate 59. 59. Spring JSF 60. 60. Spring JDF Hibernate 61. 61. Spring Data MongoDB 62. 62. Spring 常见面试问题

42. Spring Boot Redis Cache

Spring Boot Redis缓存

在本文中,我们将设置一个示例Spring Boot应用程序并将其与雷迪斯隐藏物。虽然Redis是一个开源的内存数据结构存储,用作数据库、缓存和消息代理,但本课将只演示缓存集成。

我们将利用Spring初始化器快速设置项目的工具。

Spring Boot Redis项目设置

我们将使用springinitializer工具来快速设置项目。我们将使用3个依赖项,如下所示: 下载项目并解压缩。我们使用了H2数据库依赖,因为我们将使用一个嵌入式数据库,一旦应用程序被停止,就会丢失所有数据。

Spring Boot Redis缓存Maven依赖项

虽然我们已经使用该工具完成了设置,但如果您想手动设置,我们将使用Maven build system来执行此项目,下面是我们使用的依赖项:


<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.9.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
</properties>
<dependencies>
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
  </dependency>

  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-test</artifactId>
     <scope>test</scope>
  </dependency>

  <!-- for JPA support -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>

  <!-- for embedded database support -->
  <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
  </dependency>

</dependencies>

<build>
  <plugins>
     <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
     </plugin>
  </plugins>
</build>

确保使用稳定版本的Spring Boot马文中心.

定义模型

为了将对象保存到Redis数据库中,我们定义了一个具有基本字段的Person模型对象:

package com.journaldev.rediscachedemo;

import javax.persistence.*;
import java.io.Serializable;

@Entity
public class User implements Serializable {

    private static final long serialVersionUID = 7156526077883281623L;

    @Id
    @SequenceGenerator(name = "SEQ_GEN", sequenceName = "SEQ_USER", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
    private Long id;
    private String name;
    private long followers;

    public User() {
    }

    public User(String name, long followers) {
        this.name = name;
        this.followers = followers;
    }

    //standard getters and setters

    @Override
    public String toString() {
        return String.format("User{id=%d, name="%s", followers=%d}", id, name, followers);
    }
}

这是一个有getter和setter的标准POJO。

配置Redis缓存

有了Spring Boot和Maven所需的依赖关系,我们只需在我们的应用程序.属性文件格式:


# Redis Config
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379

另外,使用@EnableCaching annotation on Spring Boot main class:

package com.journaldev.rediscachedemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class Application implements CommandLineRunner {

  private final Logger LOG = LoggerFactory.getLogger(getClass());
  private final UserRepository userRepository;

  @Autowired
  public Application(UserRepository userRepository) {
    this.userRepository = userRepository;
  }

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

  @Override
  public void run(String... strings) {
    //Populating embedded database here
    LOG.info("Saving users. Current user count is {}.", userRepository.count());
    User shubham = new User("Shubham", 2000);
    User pankaj = new User("Pankaj", 29000);
    User lewis = new User("Lewis", 550);

    userRepository.save(shubham);
    userRepository.save(pankaj);
    userRepository.save(lewis);
    LOG.info("Done saving users. Data: {}.", userRepository.findAll());
  }
}

我们添加了一个CommandLineRunner,因为我们想在嵌入式H2数据库中填充一些示例数据。

定义存储库

在展示Redis的工作原理之前,我们将为JPA相关功能定义一个存储库:

package com.journaldev.rediscachedemo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository { }

它现在还没有方法调用,因为我们不需要任何方法调用。

定义控制器

控制器是调用Redis缓存进行操作的地方。实际上,这是执行此操作的最佳位置,因为缓存与缓存直接关联,请求甚至不必输入服务代码来等待缓存结果。

以下是控制器骨架:


package com.journaldev.rediscachedemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

@RestController
public class UserController {

  private final Logger LOG = LoggerFactory.getLogger(getClass());

  private final UserRepository userRepository;

  @Autowired
  public UserController(UserRepository userRepository) {
    this.userRepository = userRepository;
  }
   ...
}

现在,要把一些东西放到缓存中,我们使用@Cacheable annotation:


@Cacheable(value = "users", key = "#userId", unless = "#result.followers < 12000")
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public User getUser(@PathVariable String userId) {
  LOG.info("Getting user with ID {}.", userId);
  return userRepository.findOne(Long.valueOf(userId));
}

在上面的映射中,getUser method will put a person into a cache named as ‘users’, identifies that person by the key as ‘userId’ and will only store a user with followers greater than 12000. This makes sure that cache is populated with users who are very popular and are often queried for.

此外,我们还特意在API调用中添加了一个log语句。现在让我们从Postman调用一些API。以下是我们拨打的电话:

localhost:8090/1
localhost:8090/1
localhost:8090/2
localhost:8090/2

如果我们注意到这些日志,它们将是:


... : Getting user with ID 1.
... : Getting user with ID 1.
... : Getting user with ID 2.

注意到什么了吗?我们进行了四次API调用,但只有三条日志语句存在。这是因为ID为2的用户拥有29000个关注者,因此,它的数据被缓存。这意味着当对其进行API调用时,数据将从缓存中返回,并且不会对此进行DB调用!

正在更新缓存

每当缓存值的实际对象值被更新时,缓存值也应该更新。这可以使用@CachePut注解完成:


@CachePut(value = "users", key = "#user.id")
@PutMapping("/update")
public User updatePersonByID(@RequestBody User user) {
  userRepository.save(user);
  return user;
}

这样,一个人将再次通过他的ID进行识别,并使用结果进行更新。

正在清除缓存

如果要从实际数据库中删除一些数据,就不再需要将其保存在缓存中了。我们可以使用@CacheEvict annotation:

@CacheEvict(value = "users", allEntries=true)
@DeleteMapping("/{id}")
public void deleteUserByID(@PathVariable Long id) {
  LOG.info("deleting person with id {}", id);
  userRepository.delete(id);
}

在上一个映射中,我们只是逐出缓存项,而不做任何其他操作。

运行Spring Boot Redis缓存应用程序

我们只需使用一个命令即可运行此应用程序:


mvn spring-boot:run

Redis缓存限制

尽管Redis速度非常快,但它在64位系统上存储任何数量的数据仍然没有限制。它只能在32位系统上存储3GB的数据。更多的可用内存会导致更高的命中率,但一旦Redis占用了太多内存,这种情况就会停止。当缓存大小达到内存限制时,旧数据将被删除,以替换新数据。

摘要

在这节课中,我们了解了powerredis Cache为我们提供了什么样的快速数据交互,以及我们如何以最小但强大的配置将其与Spring Boot集成。欢迎在下面留言。