天天看點

在Spring Boot中使用資料緩存

在Spring Boot中使用資料緩存

春節就要到了,在回家之前要趕快把今年欠下的技術債還清。so,今天繼續。Spring Boot前面已經預熱了n篇部落格了,今天我們來繼續看如何在Spring Boot中解決資料緩存問題。本篇部落格是以初識在Spring Boot中使用JPA為基礎的,先了解如何實作資料通路,然後才好實作資料緩存。OK,對于Spring Boot尚有疑問的小夥伴可以先移步這裡從SpringMVC到Spring Boot,老司機請略過。

OK,廢話不多說,開始今天的技術之旅吧。

在實際開發中,對于要反複讀寫的資料,最好的處理方式是将之在記憶體中緩存一份,頻繁的資料庫通路會造成程式效率低下,同時記憶體的讀寫速度本身就要強于硬碟。Spring在這一方面給我們提供了諸多的處理手段,而Spring Boot又将這些處理方式進一步簡化,接下來我們就來看看如何在Spring Boot中解決資料緩存問題。

#建立Project并添加資料庫驅動

Spring Boot的建立方式還是和我們前文提到的建立方式一樣,不同的是這裡選擇添加的依賴不同,這裡我們添加Web、Cache和JPA依賴,如下圖:

在Spring Boot中使用資料緩存

建立成功之後,接下來添加資料庫驅動,我還是使用MySql,在pom.xml中添加資料庫驅動,如下:

<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.40</version>
		</dependency>
      

#配置application.properties

這個application.properties的配置還是和初識在Spring Boot中使用JPA一樣,各個參數的含義我這裡也不再贅述,我們直接來看代碼:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/sang?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=sang

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent_output=true
      

#建立實體類

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private String address;
    private Integer age;

    public Person() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Person(Long id, String name, String address, Integer age) {
        this.id = id;
        this.name = name;
        this.address = address;
        this.age = age;
    }
}
      

#建立實體類的Repository

public interface PersonRepository extends JpaRepository<Person,Long> {
}
      

#建立業務類

業務接口

public interface DemoService {
    public Person save(Person person);

    public void remove(Long id);

    public Person findOne(Person person);
}
      

實作類

@Service
public class DemoServiceImpl implements DemoService {
    @Autowired
    PersonRepository personRepository;

    @CachePut(value = "people", key = "#person.id")
    @Override
    public Person save(Person person) {
        Person p = personRepository.save(person);
        System.out.println("為id、key為" + p.getId() + "資料做了緩存");
        return p;
    }

    @CacheEvict(value = "people")
    @Override
    public void remove(Long id) {
        System.out.println("删除了id、key為" + id + "的資料緩存");
        personRepository.delete(id);
    }

    @Cacheable(value = "people", key = "#person.id")
    @Override
    public Person findOne(Person person) {
        Person p = personRepository.findOne(person.getId());
        System.out.println("為id、key為" + p.getId() + "資料做了緩存");
        return p;
    }
}@Service
public class DemoServiceImpl implements DemoService {
    @Autowired
    PersonRepository personRepository;

    @CachePut(value = "people", key = "#person.id")
    @Override
    public Person save(Person person) {
        Person p = personRepository.save(person);
        System.out.println("為id、key為" + p.getId() + "資料做了緩存");
        return p;
    }

    @CacheEvict(value = "people")
    @Override
    public void remove(Long id) {
        System.out.println("删除了id、key為" + id + "的資料緩存");
        personRepository.delete(id);
    }

    @Cacheable(value = "people", key = "#person.id")
    @Override
    public Person findOne(Person person) {
        Person p = personRepository.findOne(person.getId());
        System.out.println("為id、key為" + p.getId() + "資料做了緩存");
        return p;
    }
}
      

關于這個實作類我說如下幾點:

1.@CachePut表示緩存新添加的資料或者更新的資料到緩存中,兩個參數value表示緩存的名稱為people,key表示緩存的key為person的id

2.@CacheEvict表示從緩存people中删除key為id的資料

3.@Cacheable表示添加資料到緩存中,緩存名稱為people,緩存key為person的id屬性。

#建立Controller

@RestController
public class CacheController {
    @Autowired
    DemoService demoService;

    @RequestMapping("/put")
    public Person put(Person person) {
        return demoService.save(person);
    }

    @RequestMapping("/able")
    public Person cacheable(Person person) {
        return demoService.findOne(person);
    }

    @RequestMapping("/evit")
    public String evit(Long id) {
        demoService.remove(id);
        return "ok";
    }
}
      

OK ,做完這一切我們就可以來測試我們剛剛寫的緩存了。

#測試

看我們的Controller,我們有三個位址要測試,一個一個來。當然,在 測試之前,我們先來看看初始狀态下的資料庫是什麼樣子的:

在Spring Boot中使用資料緩存

首先我們在浏覽器中通路http://localhost:8080/able?id=1,得到如下通路結果:

在Spring Boot中使用資料緩存

這個時候檢視控制台,輸出内容如下:

在Spring Boot中使用資料緩存

說是資料已經被緩存了,這個時候我們再繼續在浏覽器中重新整理繼續請求id為1的資料,會發現控制台不會繼續列印日志出來,就是因為資料已被存于緩存之中了。

接下來我們向浏覽器中輸入http://localhost:8080/put?age=47&name=奧巴牛&address=米國,通路結果如下:

在Spring Boot中使用資料緩存

這個時候檢視控制台列印的日志如下:

在Spring Boot中使用資料緩存

再檢視資料表,資料已插入成功:

在Spring Boot中使用資料緩存

此時,我們在浏覽器中輸入http://localhost:8080/able?id=106,通路剛剛插入的這條資料,結果如下:

在Spring Boot中使用資料緩存

這個時候檢視控制台,發現并沒有資料資料,就是因為資料已經處于緩存中了。

最後我們在浏覽器中輸入http://localhost:8080/evit?id=106,将資料從緩存中移除,通路結果如下:

在Spring Boot中使用資料緩存

這個時候檢視控制台,已經提示緩存移除掉了:

在Spring Boot中使用資料緩存

同時資料也從資料庫删除掉了,這個時候如果還需要該資料則需要我們繼續向表中添加資料。

#緩存技術切換

Spring Boot預設情況下使用ConcurrentMapCacheManager作為緩存技術,有的時候你可能想替換為其他的緩存方式,在Spring Boot中進行緩存的切換非常簡單,我這裡以Google提供的Guava為例,如果要使用這種緩存政策,隻需要添加相應的依賴即可,如下:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>

      

就這樣就可以了。實際上在Spring Boot中,底層使用哪一種緩存我們并不必做過多考慮,切換的方式也很簡單,如上文引入相應的依賴即可,我們隻需要把上層的邏輯寫好即可。

本文案例下載下傳:

本文GitHub位址https://github.com/lenve/JavaEETest/tree/master/Test25-Cache.

更多Spring Boot案例請移步這裡從SpringMVC到Spring Boot

以上。

繼續閱讀