Spring Boot 入門示例(十四):Spring Boot 集成 Guava Cache 實現緩存機制

Spring Boot 集成 Guava Cache 實現緩存機制

Guava Cache 是一個全內存的本地緩存實現,而且提供了線程安全機制,相比於數據庫或 Redis 存儲,訪問內存中的數據會更加高效。

Guava 官網介紹,下面的這幾種情況可以考慮使用 Guava Cache:

  • 願意消耗一些內存空間來提升速度。

  • 預料到某些鍵會被多次查詢。

  • 緩存中存放的數據總量不會超出內存容量。

所以,可以將頻繁用到的少量數據存儲到 Guava Cache 中,以提高程序性能。下面我們來看看 Guava Cache 具體用法。

添加依賴

在 pom.xml 中添加 spring-boot-starter-cacheguava 依賴。

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

<!--guava 依賴-->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.0.1-jre</version>
</dependency>

準備數據

模擬數據庫的數據

/**
 * 數據工廠,模擬數據庫的數據
 *
 * @author star
 **/
public class DataFactory {

    private DataFactory() {
    }

    private static List<UserDto> userDtoList;

    static {
        // 初始化集合
        userDtoList = new ArrayList<>();

        UserDto user = null;
        for (int i = 0; i < 5; i++) {
            user = new UserDto();
            user.setName("star" + i);
            user.setAge(23);
            userDtoList.add(user);
        }
    }

    public static List<UserDto> getUserDaoList() {
        return userDtoList;
    }
}

創建 Guava Cache 配置類

Guava Cache 配置比較簡潔,下面配置了緩存數據的過期時間是 10s,最大緩存容量是 1000 個。

@Configuration
@EnableCaching
public class GuavaCacheConfig {

    /**
     * 設置緩存管理器
     */
    @Bean
    public CacheManager cacheManager(){
        GuavaCacheManager cacheManager = new GuavaCacheManager();

        cacheManager.setCacheBuilder(CacheBuilder.newBuilder()
                // 緩存過期時間
                .expireAfterWrite(10, TimeUnit.SECONDS)
                // 緩存最大容量是 1000
                .maximumSize(1000)
        );
        return cacheManager;
    }

}

Guava Cache 除了代碼中提到的設置緩存過期時間的策略外,還有其他的策略。下面是 Guava Cache 設置緩存過期時間的策略:

  • expireAfterAccess: 當緩存項在指定的時間段內沒有被讀或寫就會被回收。

  • expireAfterWrite:當緩存項在指定的時間段內沒有更新就會被回收,如果我們認爲緩存數據在一段時間後數據不再可用,那麼可以使用該種策略。

  • refreshAfterWrite:當緩存項上一次更新操作之後的多久會被刷新。

編寫業務代碼

  • 編寫 DAO 層
/**
 * UserRepository
 *
 * @author star
 **/
@Repository
public class UserRepository {

    /**
     * 獲取用戶信息(此處是模擬的數據)
     */
    public UserDto getUserByName(String username) {
        UserDto user = getUserFromList(username);
        return user;
    }

    /**
     * 從模擬的數據集合中篩選 username 的數據
     */
    private UserDto getUserFromList(String username) {

        List<UserDto> userDaoList = DataFactory.getUserDaoList();
        for (UserDto user : userDaoList) {
            if (Objects.equals(user.getName(), username)) {
                return user;
            }
        }
        return null;
    }
}
  • 編寫 Service 層
/**
 * UserService
 *
 * @author star
 **/
@Service
@CacheConfig(cacheNames = "guavaCache") // 聲明緩存的名稱
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Cacheable(key = "#name")
    public UserDto getUserByName(String name) {
        System.out.println("從數據庫中獲取數據,而不是讀取緩存");
        return userRepository.getUserByName(name);
    }

}

由於在上一篇 Spring Boot 緩存技術 已經對緩存用法做了詳細說明,這裏就簡單介紹一下:

  • @Cacheable: 主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存。同時在查詢時,會先從緩存中獲取,若不存在纔再發起對數據庫的訪問。

  • @CachePut:配置於方法上時,能夠根據參數定義條件來進行緩存,其與 @Cacheable 不同的是,它不會去檢查緩存中是否存在之前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的緩存中,所以主要用於數據新增和修改操作上。

  • @CacheEvict:配置於方法上時,表示從緩存中移除相應數據。

  • 編寫 Controller 層

/**
 * UserResource
 *
 * @author star
 **/
@RestController
@RequestMapping("/api")
public class UserResource {

    @Autowired
    private UserService userService;

    @Autowired
    private CacheManager cacheManager;

    @GetMapping("/users/{name}")
    public ResponseEntity<UserDto> getUser(@PathVariable String name) {
        System.out.println("==================");
        UserDto user = userService.getUserByName(name);
        System.out.println(cacheManager.toString());
        return ResponseEntity.ok(user);
    }
}

演示

通過多次向接口 http://localhost:8080/api/users/star1 GET 數據來觀察效果:
get
可以看到緩存的啓用和效果如下所示:
result

後記

由於自身能力有限,若有錯誤或者不當之處,還請大家批評指正,一起學習交流!

GitHub 源碼地址:springboot-guava-cache

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章