一、引入
隨着java的慢慢學習,緩存的使用也越來越多。我們使用緩存大多數是通過api的方式來操作,厲害的人也可以自己自定義注解來簡化操作,但是看完這篇博客,以后操作注解就不會辣么麻煩了。因為spring中提供了CacheManager接口和一些注解方便我們來操作。
在我們接觸的緩存大致兩種,本地緩存與中間件緩存。spring對常用的緩存都進行了一些封裝。可以通過ctrl+h查看CacheManager的繼承類,主要有SimplerCacheManager(內部一個CurrentMap)與RedisCacheManager、EhCacheManager等。
二、demo操作技巧
在自己動手寫demo之前,希望能知道一些基礎知識。我們操作緩存是需要CacheManager與以下四種注解配合的:
-
EnableCache
開啟Cache注解功能。
-
Cacheable
根據鍵從緩存中取值,存在獲取到后直接返回。
鍵不存在則執行方法,將返回結果放入到緩存中。
-
CachePut
根據鍵從緩存中取值,無論如何,方法都會被執行,
且返回值存入緩存中
-
CacheEvict
執行方法后,刪除緩存中數據
以上四種注解,除去第一個寫在類上,后面三個都是寫在方法上,常用的參數如下:
-
value/cacheNames
定義緩存的名字
-
定義緩存的名字
-
key
key 屬性是來指定緩存數據所使用的的 key,默認使用的是方法調用傳過來的參數作為 key
-
condition、unless
支持SqEl表達式,都是判斷條件,是否使用緩存
案列:
@Cacheable(cacheNames="test",,key = "#test = 3")
此時給注解表示會獲取鍵值為test::3的key,如果不存在,就執行方法,將結果放入緩存中。
三、代碼實操
案例代碼:
@SpringBootApplication
@EnableCaching
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(App.class, args);
Demo bean = run.getBean(Demo.class);
while (true){
Scanner scanner = new Scanner(System.in);
if (scanner.hasNext()){
String next = scanner.next();
if ("1".equals(next))
bean.test1("demo");
if ("2".equals(next))
bean.test2("demo");
if ("3".equals(next))
bean.test3("demo");
}
}
}
}
@Component
public class Demo {
@Cacheable(cacheNames = "test")
public String test1(String test){
System.out.println("i am run");
return "test1";
}
@CacheEvict("test")
public String test2(String test){
System.out.println("i am run");
return "test2";
}
@CachePut(cacheNames = "test",key = "#test = 3")
public String test3(String test){
System.out.println("i am run");
return "test3";
}
}
操作結果:
1 ->輸入
i am run 緩存中添加新的緩存
3 ->輸入
i am run 緩存中的內容刷新
2 ->輸入
i am run 緩存被刪除
四、缺點
當我們使用緩存中間件的時候,我們不能使用比較復雜的數據結構,都是用string鍵值對來存去。
五、拓展提高
當我們操作cahche且使用redis默認配置的時候,我們經常會發現我們存入緩存中的數據通過工具查看會亂碼,看不懂,這里是因為我們沒有配置Cache,將redis作為緩存的話,默認是使用jdk序列化器,所以會亂碼看不懂。
這里我們可以通過自定義CacheManager來解決問題。
@Configuration
public class RedisConfig {
@Autowired
private LettuceConnectionFactory lettuceConnectionFactory;
@Bean
public RedisCacheManager redisCacheManager(){
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))//設置緩存過期時間
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); //設置序列化器
RedisCacheManager build = RedisCacheManager.builder(lettuceConnectionFactory)
.cacheDefaults(config)
.build();
return build;
}
}
希望能幫到你,如有不存請留言相互提高。