性能缓慢是开发人员经常面临的一个反复出现且复杂的问题。解决此类问题的最常见方法之一是通过缓存。实际上,这种机制允许在任何类型的应用程序的性能方面实现显着改进。问题是处理缓存并不是一件容易的事。幸运的是,Spring Boot 透明地提供了缓存,这要归功于 Spring Boot 缓存抽象,这是一种允许一致使用各种缓存方法而对代码影响最小的机制。让我们看看开始处理它应该知道的一切。
首先,我们将介绍缓存的概念。然后,我们将研究最常见的 Spring Boot 缓存相关注解,了解最重要的注解是什么,在哪里以及如何使用它们。接下来,是时候看看在撰写本文时 Spring Boot 支持的最流行的缓存引擎有哪些。最后,我们将通过一个示例了解 Spring Boot 缓存的实际应用。
什么是缓存
缓存是一种旨在提高任何类型应用程序性能的机制。它依赖于缓存,缓存可以看作是一种临时的快速访问软件或硬件组件,用于存储数据以减少处理与相同数据相关的未来请求所需的时间。处理缓存是很复杂的,但掌握这个概念对于任何开发人员来说几乎都是不可避免的。如果您有兴趣深入研究缓存、了解它是什么、它是如何工作的以及它最重要的类型是什么,您应该首先点击这个链接。
如何在 Spring Boot 应用程序中实现 Redis 缓存?
为了使用 Spring Boot 实现 Redis 缓存,我们需要创建一个小型应用程序,该应用程序将具有 CRUD 操作。然后我们将在检索、更新和删除操作中应用 Redis 缓存功能。
我们将使用 REST 创建一个 CRUD 应用程序。在这里,假设我们的实体类是 Invoice.java。为了创建一个完整的 REST 应用程序,我们将根据行业最佳实践拥有控制器、服务和存储库层。一旦我们完成了 Invoice REST Application 的开发,我们将进一步在某些方法上应用注解来获得 Redis Cache 的好处。这是在我们的应用程序中实现 Redis 缓存的分步方法。
需要引入的依赖
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
- 复制代码
配置文件
- spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
- spring.datasource.url=jdbc:mysql://localhost:3306/rediscachetest
- spring.datasource.username=root
- spring.datasource.password=****
-
- spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
- spring.jpa.show-sql=true
- spring.jpa.hibernate.ddl-auto=update
-
- spring.cache.type=redis
- spring.cache.redis.cache-null-values=true
- #spring.cache.redis.time-to-live=40000
- 复制代码
启动类注解 @EnableCaching at starter class
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.cache.annotation.EnableCaching;
-
- @SpringBootApplication
- @EnableCaching
- public class RedisAsaCacheWithSpringBootApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(RedisAsaCacheWithSpringBootApplication.class, args);
- }
- }
- 复制代码
创建 Invoice.java实体类
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @Entity
- public class Invoice implements Serializable{
-
- private static final long serialVersionUID = -4439114469417994311L;
-
- @Id
- @GeneratedValue
- private Integer invId;
- private String invName;
- private Double invAmount;
- }
- 复制代码
创建一个接口 InvoiceRepository.java
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.stereotype.Repository;
- import com.dev.springboot.redis.model.Invoice;
-
- @Repository
- public interface InvoiceRepository extends JpaRepository<Invoice, Integer> {
-
- }
- 复制代码
- import org.springframework.http.HttpStatus;
- import org.springframework.web.bind.annotation.ResponseStatus;
-
- @ResponseStatus(HttpStatus.NOT_FOUND)
- public class InvoiceNotFoundException extends RuntimeException {
-
- private static final long serialVersionUID = 7428051251365675318L;
-
- public InvoiceNotFoundException(String message) {
- super(message);
- }
- }
- 复制代码
一个具体的实现类,中间包含一些增删改查的方法
- import com.dev.springboot.redis.model.Invoice;
- import java.util.List;
-
- public interface InvoiceService {
-
- public Invoice saveInvoice(Invoice inv);
- public Invoice updateInvoice(Invoice inv, Integer invId);
- public void deleteInvoice(Integer invId);
- public Invoice getOneInvoice(Integer invId);
- public List
getAllInvoices(); - }
- 复制代码
- import java.util.List;
- 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.stereotype.Service;
- import com.dev.springboot.redis.exception.InvoiceNotFoundException;
- import com.dev.springboot.redis.model.Invoice;
- import com.dev.springboot.redis.repo.InvoiceRepository;
-
- @Service
- public class InvoiceServiceImpl implements InvoiceService {
-
- @Autowired
- private InvoiceRepository invoiceRepo;
-
- @Override
- public Invoice saveInvoice(Invoice inv) {
-
- return invoiceRepo.save(inv);
- }
-
- @Override
- @CachePut(value="Invoice", key="#invId")
- public Invoice updateInvoice(Invoice inv, Integer invId) {
- Invoice invoice = invoiceRepo.findById(invId)
- .orElseThrow(() -> new InvoiceNotFoundException("Invoice Not Found"));
- invoice.setInvAmount(inv.getInvAmount());
- invoice.setInvName(inv.getInvName());
- return invoiceRepo.save(invoice);
- }
-
- @Override
- @CacheEvict(value="Invoice", key="#invId")
- // @CacheEvict(value="Invoice", allEntries=true) //in case there are multiple records to delete
- public void deleteInvoice(Integer invId) {
- Invoice invoice = invoiceRepo.findById(invId)
- .orElseThrow(() -> new InvoiceNotFoundException("Invoice Not Found"));
- invoiceRepo.delete(invoice);
- }
-
- @Override
- @Cacheable(value="Invoice", key="#invId")
- public Invoice getOneInvoice(Integer invId) {
- Invoice invoice = invoiceRepo.findById(invId)
- .orElseThrow(() -> new InvoiceNotFoundException("Invoice Not Found"));
- return invoice;
- }
-
- @Override
- @Cacheable(value="Invoice")
- public List<Invoice> getAllInvoices() {
- return invoiceRepo.findAll();
- }
- }
- 复制代码
添加Controller接口,进行请求测试
- import java.util.List;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.http.ResponseEntity;
- import org.springframework.web.bind.annotation.DeleteMapping;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.PutMapping;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import com.dev.springboot.redis.model.Invoice;
- import com.dev.springboot.redis.service.InvoiceService;
-
- @RestController
- @RequestMapping("/invoice")
- public class InvoiceController {
-
- @Autowired
- InvoiceService invoiceService;
-
- @PostMapping("/saveInv")
- public Invoice saveInvoice(@RequestBody Invoice inv) {
- return invoiceService.saveInvoice(inv);
- }
-
- @GetMapping("/allInv")
- public ResponseEntity
> getAllInvoices(){
- return ResponseEntity.ok(invoiceService.getAllInvoices());
- }
-
- @GetMapping("/getOne/{id}")
- public Invoice getOneInvoice(@PathVariable Integer id) {
- return invoiceService.getOneInvoice(id);
- }
-
- @PutMapping("/modify/{id}")
- public Invoice updateInvoice(@RequestBody Invoice inv, @PathVariable Integer id) {
- return invoiceService.updateInvoice(inv, id);
- }
-
- @DeleteMapping("/delete/{id}")
- public String deleteInvoice(@PathVariable Integer id) {
- invoiceService.deleteInvoice(id);
- return "Employee with id: "+id+ " Deleted !";
- }
- }