SpringBoot緩存篇Ⅰ--- 緩存抽象

緩存是每個系統應該考慮的功能,它能夠用來加速系統的訪問,提高系統性能,例如要常常訪問的高頻熱點數據,例如某一個商品網站的商品信息,商品信息存儲在數據庫中,若每次訪問都要查詢數據庫的話,這樣的操做耗時太大了,因此咱們須要作一個緩存中間件,這樣咱們不須要查詢數據庫了,直接查詢緩存,若緩存中有,能夠直接返回,若沒有再查詢數據庫,而後放到緩存中,這樣咱們的系統性能就獲得了很大的提高,由於咱們的應用程序和緩存的交互是十分快的。java

還有一個應用場景是驗證碼,驗證碼是臨時性數據,一段時間內有效,用完就能夠刪除,這樣的數據無需存在數據庫中,因此可使用緩存來存儲這些臨時性數據,等用戶使用完後自動讓它清除。mysql

1、JSR107(瞭解)spring

JSR是Java規範請求,故名思議提交Java規範,你們一同遵照這個規範的話,會讓你們‘溝通’起來更加輕鬆。咱們一直使用的JDBC就一個訪問數據庫的一個規範的例子。JSR-107呢就是關於如何使用緩存的規範。sql

Java Caching定義了5個核心接口,分別是CachingProvider, CacheManager, Cache, EntryExpiry:數據庫

1.CachingProvider定義了建立、配置、獲取、管理和控制多個CacheManager。一個應用能夠在運行期訪問多個CachingProvider。api

2.CacheManager定義了建立、配置、獲取、管理和控制多個惟一命名的Cache,這些Cache存在於CacheManager的上下文中。一個CacheManager僅被一個CachingProvider所擁有。數組

3.Cache是一個相似Map的數據結構並臨時存儲以Key爲索引的值。一個Cache僅被一個CacheManager所擁有。緩存

4.Entry是一個存儲在Cache中的key-value對。數據結構

5.Expiry每個存儲在Cache中的條目有一個定義的有效期。一旦超過這個時間,條目爲過時的狀態。一旦過時,條目將不可訪問、更新和刪除。緩存有效期能夠經過ExpiryPolicy設置。mybatis

使用時須要導入以下包:

<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
</dependency>

 JSR107在真正生產開發當中使用的很少,爲了簡化開發Spring提供了本身的緩存抽象,也定義了一些相似的註解,在實際開發中通常用Spring的緩存抽象。

 

、Spring的緩存抽象

Spring框架自身並無實現緩存解決方案,可是從3.1開始定義了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口,提供對緩存功能的聲明,可以與多種流行的緩存實現集成。

幾個重要概念&緩存註解

 

 

緩存體驗

1.搭建基本環境(簡單的步驟這裏就不給代碼演示了)

1).建立department和employee表

2).建立javabean封裝數據(簡單java實體類)

3).整合mybatis操做數據庫

spring.datasource.url=jdbc:mysql://localhost:3306/spring_cache?useUnicode=true&characterEncoding=UTF8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
#驅動會根據url自行判斷
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#開啓駝峯命名匹配規則
mybatis.configuration.map-underscore-to-camel-case=true

2.緩存快速實現

1).開啓基於註解的緩存@EnableCaching

@MapperScan("com.wang.cache.mapper")
@SpringBootApplication
@EnableCaching //開啓基於註解的緩存
public class Springboot01CacheApplication {

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

}

2).給方法加上緩存標註

@Service
public class EmpService {
    @Autowired
    EmployeeMapper employeeMapper;

    @Cacheable(cacheNames = {"emp"})
    public Employee getEmp(Integer id){
       return employeeMapper.getEmployeeById(id);
    }
}

3).啓動項目測試,調用這個方法後,查看日誌是否打印,若只在第一次訪問的時候打印數據庫日誌,說明該結果已經被緩存了

@Cacheable屬性

cacheNames/value:指定緩存的名字,能夠指定將方法的結果放在哪一個緩存中,能夠是數組的方式指定多個緩存

key:緩存數據使用的key,能夠用它來指定,默認使用方法參數的值 1-方法的返回值 編寫SpEL #id 參數id的值 #a0 #p0 #root.args[0]

keyGenerator:key的生成器,能夠本身指定key的生成器的組件id(key與keyGenerator二選一使用)

/**
 * 緩存配置類
 */
@Configuration
public class MyCacheConfig {
    @Bean("myKeyGenerator")
    public KeyGenerator keyGenerator(){
       return new KeyGenerator(){

            @Override
            public Object generate(Object o, Method method, Object... objects) {
                return method.getName()+"["+Arrays.asList(objects) +"]";
            }
        };
    }

}
  @Cacheable(cacheNames = {"emp"},keyGenerator = "myKeyGenerator")
    public Employee getEmp(Integer id){
       return employeeMapper.getEmployeeById(id);
    }

cacheManager:指定緩存管理器,或者指定緩存解析器(二選一)

condition:自定符合條件的狀況下才緩存

  @Cacheable(cacheNames = {"emp"},keyGenerator = "myKeyGenerator",condition = "#id>1")
    public Employee getEmp(Integer id){
       return employeeMapper.getEmployeeById(id);
    }

unless:否認緩存,當unless指定的條件爲true,方法的返回值不會緩存,能夠獲取到結果進行判斷(#result能夠取出結果)

  @Cacheable(cacheNames = {"emp"},keyGenerator = "myKeyGenerator",unless = "#a0==2")
    public Employee getEmp(Integer id){
       return employeeMapper.getEmployeeById(id);
    }

sync:是否使用異步模式

 

@CachePut

@Cacheable調用時機是在方法以前調用,若緩存中有了則調用緩存中的方法,若緩存中沒有則調用該方法。

@CachePut的調用時機是在方法以後調用,先調用目標方法,而後將目標方法的結果緩存起來,注意該註解標註後不管是怎麼樣都會調用目標方法

測試@CachePut緩存:

1). 查詢1號員工,查到的結果會放到緩存中

2). 查詢以前的結果,看看有沒有調用目標查詢方法,如沒有調用說明已經被緩存了

3). 更新1號員工

  @CachePut(value = "emp")
    public Employee updateEmp(Employee employee){
         System.out.println("updateEmp:"+employee);
         employeeMapper.updateEmployee(employee);
        return employee;
    }

4). 此時查詢員工發現查詢的是更新前的數據,緣由key默認是傳入的employee對象,而查詢的key是員工的id,1號員工沒有更新查詢的緩存,因此應該指定key,保證與查詢的key相同,下面有兩種指定key的方式:

    1.key="#employee.id",使用傳入的參數的員工id

    2.key="#result.id",使用返回後的id(@Cacheable沒法用result,由於是在方法運行以前調用的)

 @CachePut(value = "emp",key="#result.id")
    public Employee updateEmp(Employee employee){
         System.out.println("updateEmp:"+employee);
         employeeMapper.updateEmployee(employee);
        return employee;
    }

重複上述測試步驟,若查詢的結果是更新後的數據,而且沒有調用查詢員工的service方法,說明該註解起做用了,並且同時更新了數據與緩存。

@CacheEvict

屬性詳解

key :制定要清除的數據,默認傳入的參數爲key

allEntries = true,指定這個緩存中全部數據

beforeInvocation:緩存的清除默認是否在方法執行以前執行,默認緩存清除操做是在方法運行以後執行

beforeInvocation = true 表示清楚在方法執行以前執行,不管方法是否異常,都會執行清除

   @CacheEvict(value = "emp",key="#id"/*,allEntries = true*//*,beforeInvocation = true*/)
    public void deleteEmp(Integer id){
        System.out.println("delEmp"+id);
        //int i = 1/0;
    }

@Caching

使用該註解能夠配置多個緩存註解:

@Caching(
cacheable = {
@Cacheable(value = "emp",key="#lastName")
},
put = {
@CachePut(value = "emp",key="#result.id"), //將返回的員工id也放到緩存中
@CachePut(value = "emp",key="#result.email")
}
)
public Employee getEmpByLastName(String lastName){
return employeeMapper.getEmpByLastName(lastName);
}

@CacheConfig

該註解是在類上加的,主要做用是抽取緩存的公共配置,在這裏配置的緩存將做用於該類的全部方法。

@CacheConfig(cacheNames = "emp") //抽取緩存的公共配置
@Service
public class EmpService {

}
相關文章
相關標籤/搜索