#SpringBoot實現緩存

簡介

Spring 定義 CacheManager 和 Cache 接口用來統一不一樣的緩存技術。例如 JCache、 EhCache、 Hazelcast、 Guava、 Redis 等。在使用 Spring 集成 Cache 的時候,咱們須要註冊實現的 CacheManager 的 Bean。Spring Boot 默認使用的是 SimpleCacheConfiguration,即便用 ConcurrentMapCacheManager 來實現的緩存。spring

CacheManager:緩存管理器,管理各類緩存組件

CacheManager 描述
SimpleCacheManager 使用檢點 Collection 來存儲緩存,主要用於測試
ConcurrentMapCacheManager 使用 ConcurrentMap 存儲緩存
NoOpCacheManager 僅用於測試,不會實際存儲緩存
EhCacheCacheManager 使用 EhCache 做爲緩存技術
GuavaCacheManager 使用 Guava 做爲緩存技術
HazelcastCacheManager 使用 Hazelcast 做爲緩存技術
JCacheCacheManager 支持 JCache(JSR-107)標準的實現做爲緩存技術
RedisCacheManager 使用 Redis 做爲緩存技術

Cache 註解詳解

1. @CacheConfig

@CacheConfig:主要用於配置該類中會用到的一些共用的緩存配置。
在這裏 @CacheConfig(cacheNames = 「users」):配置了該數據訪問對象中返回的內容將存儲於名爲 users 的緩存對象中,咱們也能夠不使用該註解,直接經過 @Cacheable 本身配置緩存集的名字來定義。數據庫

2. @Cacheable

@Cacheable:主要針對方法配置,可以根據方法的請求參數對其結果進行緩存。同時在查詢時,會先從緩存中獲取,若不存在纔再發起對數據庫的訪問。該註解主要有下面幾個參數:api

  • value、cacheNames:兩個等同的參數(cacheNames 爲Spring 4 新增,做爲 value 的別名),用於指定緩存存儲的集合名。因爲 Spring 4 中新增了 @CacheConfig,所以在 Spring 3 中本來必須有的 value 屬性,也成爲非必需項了。
  • key:緩存對象存儲在 Map 集合中的 key 值,非必需,缺省按照函數的全部參數組合做爲 key 值,若本身配置需使用 SpEL表 達式,好比:@Cacheable(key = 「#p0」):使用函數第一個參數做爲緩存的 key 值,更多關於 SpEL 表達式的詳細內容可參考官方文檔。
  • condition:緩存對象的條件,非必需,也需使用SpEL表達式,只有知足表達式條件的內容纔會被緩存,好比:@Cacheable(key = 「#p0」, condition = 「#p0.length() < 3」),表示只有當第一個參數的長度小於3的時候纔會被緩存,若作此配置上面的AAA用戶就不會被緩存,讀者可自行實驗嘗試。
  • unless:另一個緩存條件參數,非必需,需使用 SpEL 表達式。它不一樣於 condition 參數的地方在於它的判斷時機,該條件是在函數被調用以後才作判斷的,因此它能夠經過對 result 進行判斷。
  • keyGenerator:用於指定 key 生成器,非必需。若須要指定一個自定義的 key 生成器,咱們須要去實現org.springframework.cache.interceptor.KeyGenerator 接口,並使用該參數來指定。須要注意的是,該參數與 key 是互斥的。
  • cacheManager:用於指定使用哪一個緩存管理器,非必需。只有當有多個時才須要使用。
  • cacheResolver:用於指定使用那個緩存解析器,非必需。需經過
    org.springframework.cache.interceptor.CacheResolver 接口來實現本身的緩存解析器,並用該參數指定。數組

3. @CachePut

@CachePut:配置於方法上,可以根據參數定義條件來進行緩存,它與 @Cacheable 不一樣的是,它不會去檢查緩存中是否存在以前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入緩存中,因此主要用於數據新增和修改操做上。它的參數與 @Cacheable 相似,具體功能可參考上面對 @Cacheable 參數的解析。緩存

4. @CacheEvict

@CacheEvict:配置於函數上,一般用在刪除方法上,用來從緩存中移除相應數據。除了同 @Cacheable 同樣的參數以外,它還有下面兩個參數:app

  • allEntries:非必需,默認爲 false。當爲 true 時,會移除全部數據。
  • beforeInvocation:非必需,默認爲 false,會在調用方法以後移除數據;當爲 true 時,會在調用方法以前移除數據。

搭建 Spring Boot 默認緩存

1. 開啓緩存支持

在啓動類上添加 @EnableCaching 開啓緩存支持,進行自動掃描。less

@SpringBootApplication
@EnableCaching  // 開啓緩存功能
public class CacheApplication {

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

2. 添加 spring-boot-starter-cache 依賴

在 pom.xml 中添加 spring-boot-starter-cache 依賴。函數

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

3. 準備數據

模擬數據庫數據

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

    private DataFactory() {
    }

    private static List<UserDto> userDtoList;

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

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

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

編寫緩存業務代碼

/**
 * UserRepository
 *
 * @author star
 **/
@Repository
public class UserRepository {

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

    /**
     * 刪除用戶信息
     */
    public List<UserDto> deleteUser(String username) {

        List<UserDto> userDaoList = DataFactory.getUserDaoList();
        userDaoList.remove(getUserFromList(username));

        return userDaoList;
    }

    /**
     * 新增數據
     */
    public List<UserDto> save(String username) {
        // 添加到集合
        List<UserDto> userDaoList = DataFactory.getUserDaoList();
        for (UserDto userDto : userDaoList) {
            // 不能重複添加相同數據
            if (Objects.equals(userDto.getName(), username)) {
                return userDaoList;
            }
        }
        UserDto user = new UserDto();
        user.setName(username);
        user.setAge("50");
        userDaoList.add(user);

        return userDaoList;
    }

    /**
     * 從模擬的數據集合中篩選 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;
    }
}
/**
 * UserService
 *
 * @author star
 **/
@Service
@CacheConfig(cacheNames = "users")// 指定緩存名稱,在本類中是全局的
public class UserService {

    @Autowired
    private UserRepository userRepository;

    /**
     * 緩存 key 是 username 的數據到緩存 users 中,
     * 若是沒有指定 key,則方法參數做爲 key 保存到緩存中
     */
    @Cacheable(key = "#username")
    public UserDto getUser(String username) {
        System.out.println("從數據庫中獲取數據,而不是讀取緩存");
        return userRepository.getUser(username);
    }


    /**
     * 新增或更新緩存中的數據
     */
    @CachePut(key = "#username")
    public List<UserDto> save(String username) {
        return userRepository.save(username);
    }

    /**
     * 從緩存 users 中刪除 key 是 username 的數據
     */
    @CacheEvict(key = "#username")
    public List<UserDto> deleteUser(String username) {
        System.out.println("從數據庫中刪除數據,以及緩存中的數據");
        return userRepository.deleteUser(username);
    }
}
/**
 * CacheResource
 *
 * @author star
 **/
@RestController
@RequestMapping("/api")
public class CacheResource {

    @Autowired
    private UserService userService;

    @GetMapping("/users/{username}")
    public ResponseEntity<UserDto> getUser(@PathVariable String username) {
        // 獲取數據
        UserDto user = userService.getUser(username);
        return ResponseEntity.ok(user);
    }

    @PutMapping("/users/{username}")
    public ResponseEntity<List<UserDto>> save(@PathVariable String username) {
        List<UserDto> userDtoList = userService.save(username);

        return ResponseEntity.ok(userDtoList);
    }

    @DeleteMapping("/users/{username}")
    public ResponseEntity<List<UserDto>> delete(@PathVariable String username) {
        List<UserDto> userDtoList = userService.deleteUser(username);

        return ResponseEntity.ok(userDtoList);
    }
}

啓動服務:
訪問:http://localhost:8080/api/users/star1
相關文章
相關標籤/搜索