博客 / 詳情

返回

SpringCache緩存

  一、 SpringCache緩存介紹


  Spring Cache是一個框架,實現了基於註解的緩存功能,只需要簡單地加一個註解,就能實現緩存功能,大大簡化我們在業務中操作緩存的代碼。

  Spring Cache只是提供了一層抽象,底層可以切換不同的cache實現。具體就是通過CacheManager接口來統一不同的緩存技術。CacheManager是Spring提供的各種緩存技術抽象接口。

  針對不同的緩存技術需要實現不同的CacheManager:

  CacheManager 描述
  EhCacheCacheManager 使用EhCache作為緩存技術
  GuavaCacheManager 使用Google的GuavaCache作為緩存技術
  RedisCacheManager 使用Redis作為緩存技術


  二、 SpringCache註解


  在SpringCache中提供了很多緩存操作的註解,常見的是以下的幾個:

  註解 説明
  @EnableCaching 開啓緩存註解功能
  @Cacheable 在方法執行前spring先查看緩存中是否有數據,如果有數據,則直接返回緩存數據;若沒有數據,調用方法並將方法返回值放到緩存中
  @CachePut 將方法的返回值放到緩存中
  @CacheEvict 將一條或多條數據從緩存中刪除


2.1 @CachePut註解


  @CachePut 説明:

  ​ 作用: 將方法返回值,放入緩存

​   value: 緩存的名稱, 每個緩存名稱下面可以有很多key

  ​ key: 緩存的key ----------> 支持Spring的表達式語言SPEL語法

 

使用示例:在save方法上加註解@CachePut。當前UserController的save方法是用來保存用户信息的,我們希望在該用户信息保存到數據庫的同時,也往緩存中緩存一份數據,我們可以在save方法上加上註解 @CachePut,用法如下:

 

@CachePut(value = "userCache", key = "#user.id")
@PostMapping
public User save(User user){
    userService.save(user);
    return user;
}

 

key的寫法如下:

​   #user.id : #user指的是方法形參的名稱, id指的是user的id屬性 , 也就是使用user的id屬性作為key ;

​   #user.name: #user指的是方法形參的名稱, name指的是user的name屬性 ,也就是使用user的name屬性作為key ;

​   #result.id : #result代表方法返回值,該表達式 代表以返回對象的id屬性作為key ;

  ​ #result.name : #result代表方法返回值,該表達式 代表以返回對象的name屬性作為key ;

 

2.2 @CacheEvict註解


@CacheEvict 説明:

​   作用: 清理指定緩存

​   value: 緩存的名稱,每個緩存名稱下面可以有多個key

​   key: 緩存的key ----------> 支持Spring的表達式語言SPEL語法

使用示例: 在 delete 方法上加註解@CacheEvict。當我們在刪除數據庫user表的數據的時候,我們需要刪除緩存中對應的數據,此時就可以使用@CacheEvict註解, 具體的使用方式如下:

 

 

@CacheEvict(value = "userCache",key = "#p0")  //#p0 代表第一個參數
//@CacheEvict(value = "userCache",key = "#id") //#id 代表變量名為id的參數
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id){
    userService.removeById(id);
}

 


2.3 @Cacheable註解


@Cacheable 説明:

​   作用: 在方法執行前,spring先查看緩存中是否有數據,如果有數據,則直接返回緩存數據;若沒有數據,調用方法並將方法返回值放到緩存中

​   value: 緩存的名稱,每個緩存名稱下面可以有多個key

​   key: 緩存的key ----------> 支持Spring的表達式語言SPEL語法

 

使用情況1:在getById上加註解@Cacheable

 

@Cacheable(value = "userCache",key = "#id")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
    User user = userService.getById(id);
    return user;
}


  當我們在測試時,查詢一個數據庫不存在的id值,第一次查詢緩存中沒有,也會查詢數據庫。而第二次再查詢時,會發現,不再查詢數據庫了,而是直接返回,那也就是説如果根據ID沒有查詢到數據,那麼會自動緩存一個null值。

  我們能不能做到,當查詢到的值不為null時,再進行緩存,如果為null,則不緩存呢? 答案是可以的。

 

  使用情況2: 緩存非null值。

  在@Cacheable註解中,提供了兩個屬性分別為: condition, unless 。

    condition : 表示滿足條件時才緩存數據;

    unless : 表示滿足條件則不緩存 ; 與上述的condition是反向的 ;

 

@Cacheable(value = "userCache",key = "#id", unless = "#result == null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
    User user = userService.getById(id);
    return user;
}


  注意: 此處,我們使用的時候只能夠使用 unless, 因為在condition中,我們是無法獲取到結果 #result的。

 

  使用情況3: 在list方法上加註解@Cacheable。

  在list方法中進行查詢時,有兩個查詢條件,如果傳遞了id,根據id查詢; 如果傳遞了name, 根據name查詢,那麼我們緩存的key在設計的時候,就需要既包含id,又包含name。 具體的代碼實現如下:

@Cacheable(value = "userCache",key = "#user.id + '_' + #user.name")
@GetMapping("/list")
public List<User> list(User user){
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(user.getId() != null,User::getId,user.getId());
    queryWrapper.eq(user.getName() != null,User::getName,user.getName());
    List<User> list = userService.list(queryWrapper);
    return list;
}

 

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.