springboot整合spring Cache(redis)

      網(wǎng)友投稿 827 2025-04-01

      前言

      前面有介紹過spring整合redis和redis的一些注意點(diǎn),在實(shí)際開發(fā)中,spring cache方便簡(jiǎn)化的緩存操作的大部分內(nèi)容。通過注解的方式實(shí)現(xiàn)緩存。

      閱讀前推薦先閱讀:redis緩存介紹。和springboot整合redis

      springboot整合spring Cache(redis)

      緩存抽象的核心是將緩存應(yīng)用于Java方法,從而根據(jù)緩存中可用的信息減少執(zhí)行次數(shù)。也就是說,每次調(diào)用目標(biāo)方法時(shí),抽象都會(huì)應(yīng)用一種緩存行為,該行為檢查該方法是否已針對(duì)給定參數(shù)執(zhí)行。

      如果已執(zhí)行,則返回緩存的結(jié)果,而不必執(zhí)行實(shí)際方法。

      如果該方法尚未執(zhí)行,則執(zhí)行該方法,并將結(jié)果緩存并返回給用戶,以便下次調(diào)用該方法時(shí),返回緩存的結(jié)果。

      這樣,對(duì)于給定的一組參數(shù),昂貴的方法(無論是CPU還是IO)只能執(zhí)行一次,并且重用結(jié)果而不必再次實(shí)際執(zhí)行該方法。

      在緩存框架出現(xiàn)之前,要么公司自己寫緩存框架造輪子,要么在每個(gè)service中手動(dòng)修改調(diào)用redis進(jìn)行存儲(chǔ)或者更新(刪除).一旦業(yè)務(wù)邏輯代碼有變,將造成不小的維護(hù)負(fù)擔(dān)。并且代碼量也很大,使得項(xiàng)目看起來很臃腫!

      spring cache的出現(xiàn)用于簡(jiǎn)化對(duì)緩存的操作,你只需要配置緩存的cacheManager,然后按照一些簡(jiǎn)單的序列化配置,在service層即可使用注解的形式對(duì)項(xiàng)目邏輯無侵入的調(diào)用緩存。

      方法介紹

      觸發(fā) 緩存填充。即:如果有緩存從緩存中直接拿數(shù)據(jù)(就不走service了),如果沒緩存那么就執(zhí)行service。將service中的值傳到緩存中(執(zhí)行service)。

      多個(gè)名稱:緩存可能有一個(gè)名字或者多個(gè)名字,那么你可以@Cacheable("books")或者@Cacheable({"books", "isbns"})表示。

      自定義key:大家對(duì)同一個(gè)接口進(jìn)行查詢,可能有多個(gè)參數(shù),那么你可以自定義key。類似@Cacheable(value = "getuser",key = "#username")這樣寫法,這個(gè)規(guī)則和mybatis注解很像,但也有點(diǎn)區(qū)別也可以自行拼湊。

      條件緩存:有些數(shù)據(jù)你若不想所有都想走緩存,當(dāng)然也可以設(shè)置條件緩存,比如你若想讓兩個(gè)字的姓名緩存,那么你可以@Cacheable(value = "getuser",key = "#username",condition="#username.length() < 3")這樣寫法

      上鎖:@Cacheable(value = "getuser",key = "#username",sync = true)對(duì)有些數(shù)據(jù),你可能不想讓他并發(fā)執(zhí)行,那么可以假設(shè)sync關(guān)鍵字。當(dāng)然,如果是分布式或者多臺(tái)服務(wù)器需要考慮分布式鎖實(shí)現(xiàn)。

      @Cacheable(value = "getalluser") public List getalluser() { /* 假設(shè)數(shù)據(jù)從數(shù)據(jù)庫查出啦。有這么兩條 */ user user1=new user("bigsai","12345","man"); user user2=new user("給我star","謝謝","man"); Listlist=new ArrayList<>(); list.add(user1); list.add(user2); return list; } //獲取user 如果沒有緩存將執(zhí)行l(wèi)og @Cacheable(value = "getuser",key = "#username") public user getuserbyname(String username) { //假設(shè)該數(shù)據(jù)從mysql查詢結(jié)果如下 user user=new user(username,"123","women"); logger.info("執(zhí)行方法cacheable,從mysql查詢"); return user; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      觸發(fā) 緩存逐出。即刪除緩存。執(zhí)行之后將刪除緩存。

      用法和前面相似@CacheEvict(value = "getuser",key = "#username")

      但是若想刪除getuser下所有緩存目錄,那么加個(gè)參數(shù)@CacheEvict(value = "getuser",key = "#username",allEntries = true)其中allEntries就是刪除所有的意思。當(dāng)需要清除整個(gè)緩存區(qū)域時(shí),此選項(xiàng)會(huì)派上用場(chǎng)。而不是逐出每個(gè)條目。

      更新緩存而不會(huì)干擾方法執(zhí)行。即:不管有沒有緩存。每次都執(zhí)行方法,將方法得到的數(shù)據(jù)更新到緩存之中。起到update的功能。

      需要注意的是,在更新過程中可能有并發(fā)的存在。你可以設(shè)置鎖.參考Cacheable用法

      重新組合要應(yīng)用于方法的多個(gè)緩存操作。

      有時(shí),需要指定相同類型(例如@CacheEvict或 @CachePut)的多個(gè)注釋- 例如,因?yàn)椴煌?a target="_blank" href="http://m.bai1xia.com/news/tags-5931.html"style="font-weight:bold;">高速緩存之間的條件或鍵表達(dá)式不同。@Caching允許多個(gè)嵌套 @Cacheable,@CachePut和@CacheEvict注解相同的方法來使用。以下示例使用兩個(gè)@CacheEvict注釋:

      @Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })

      此操作可能是一個(gè)方法操作更新、刪除不同的緩存。具體使用需要考慮情景。

      在類級(jí)別共享一些常見的緩存相關(guān)設(shè)置。

      此方法針對(duì)同一個(gè)類中一些共同操作,簡(jiǎn)便操作和代碼量。

      到目前為止,我們已經(jīng)看到緩存操作提供了許多自定義選項(xiàng),您可以為每個(gè)操作設(shè)置這些選項(xiàng)。但是,如果某些自定義選項(xiàng)適用于該類的所有操作,則它們可能會(huì)很繁瑣。例如,指定用于類的每個(gè)高速緩存操作的高速緩存的名稱可以由單個(gè)類級(jí)定義替換。這是@CacheConfig 發(fā)揮作用的地方。以下示例用于@CacheConfig設(shè)置緩存的名稱:

      @CacheConfig("books") public class BookRepositoryImpl implements BookRepository { @Cacheable public Book findBook(ISBN isbn) {...} }

      1

      2

      3

      4

      5

      6

      具體整合

      step1:創(chuàng)建springboot工程,省略部分截圖

      step2:添加maven依賴

      org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-cache org.apache.commons commons-pool2 org.springframework.boot spring-boot-starter-web

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      step3: 配置application.properties

      spring.redis.host=127.0.0.1 spring.redis.password= spring.redis.port= 6379 spring.redis.timeout=10000 spring.cache.type=redis logging.level.com.redisCache=debug spring.redis.database=3 spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=-1 spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      step4: config目錄下建立配置文件(緩存注入對(duì)象配置,以及序列化相關(guān)配置,和前文redis差不多)

      這里面需要注意的是里面有關(guān)于redis的一些配置。在項(xiàng)目中防止多個(gè)項(xiàng)目公用一個(gè)redis可以在redis前面加個(gè)前綴(通常是項(xiàng)目名)。

      過期時(shí)間一定要設(shè)置,并且過期策略還需要根據(jù)項(xiàng)目需求具體踩坑設(shè)置。

      package com.redisCache.config; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.cache.CacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.io.Serializable; import java.time.Duration; import java.util.*; @Configuration @AutoConfigureAfter(RedisAutoConfiguration.class) public class RedisConfiguration { @Bean public RedisTemplate redisTemplate(LettuceConnectionFactory redisConnectionFactory) { RedisTemplate template = new RedisTemplate<>(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean(name = "cacheManager") @Primary public CacheManager cacheManager( RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() // .entryTtl(Duration.ofSeconds(50))設(shè)置過期時(shí)間 .disableCachingNullValues() .computePrefixWith(cacheName -> "rediscache".concat(":").concat(cacheName).concat(":"))//rediscache可以改成你的項(xiàng)目名 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(cacheConfiguration) .build(); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      step5:創(chuàng)建pojo對(duì)象和controller

      pojo:

      package com.redisCache.pojo; import java.io.Serializable; public class user implements Serializable { private String name; private String password; private String sex; public user(String name,String password,String sex) { this.name=name; this.password=password; this.sex=sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      service:

      package com.redisCache.service; import com.redisCache.pojo.user; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; @Service public class redisService { Logger logger= LoggerFactory.getLogger(redisService.class); @Cacheable(value = "getalluser") public List getalluser() { /* 假設(shè)數(shù)據(jù)從數(shù)據(jù)庫查出啦。有這么兩條 */ user user1=new user("bigsai","12345","man"); user user2=new user("給我star","謝謝","man"); Listlist=new ArrayList<>(); list.add(user1); list.add(user2); return list; } //獲取user 如果沒有緩存將執(zhí)行l(wèi)og @Cacheable(value = "getuser",key = "#username") public user getuserbyname(String username) { //假設(shè)該數(shù)據(jù)從mysql查詢結(jié)果如下 user user=new user(username,"123","women"); logger.info("執(zhí)行方法cacheable,從mysql查詢"); return user; } //更新user。每次都執(zhí)行 @CachePut(value = "getuser",key = "#username") public user updateuser(String username,String password) { //假設(shè)更新用戶賬號(hào)密碼re user user=new user(username,"123","women"); user.setPassword(password); logger.info("執(zhí)行方法cacheput,再數(shù)據(jù)庫更新返回"); return user; } //刪除緩存,其中condition可加可不加,本句意思是只有當(dāng)姓名為bigsai @CacheEvict(value = "getuser",key = "#username",allEntries = true) public String deleteuser(String username) { return "移除成功"; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      controller:

      package com.redisCache.controller; import com.redisCache.pojo.user; import com.redisCache.service.redisService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class redisController { private final static Logger log= LoggerFactory.getLogger(redisController.class); @Autowired(required = false) redisService redisService; @GetMapping("getalluser") public Listgetalluser() { return redisService.getalluser(); } @GetMapping("getuser/{username}") public user getuser(@PathVariable String username) { return redisService.getuserbyname(username); } @GetMapping("updateuser/{username}/{password}") public user updateuser(@PathVariable String username,@PathVariable String password) { return redisService.updateuser(username,password); } @GetMapping("deleteuser/{username}") public String deleteuser(@PathVariable String username) { return redisService.deleteuser(username); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      step6:在啟動(dòng)類加上允許緩存注解

      測(cè)試與總結(jié)

      getalluser:

      getuser:

      update:更新上一條

      delete:整個(gè)移除(前面講到allentries參數(shù)作用,不妨自己測(cè)試)

      可以看得到緩存的一些操作正常完成了

      上文只是一個(gè)簡(jiǎn)單的整合過程,具體使用還需要自己踩坑才行。而緩存的深度遠(yuǎn)遠(yuǎn)不是這么簡(jiǎn)單,還需要自己挖掘。

      項(xiàng)目完整github地址。不吝嗇star的大哥求個(gè)star。

      最后,歡迎關(guān)注個(gè)人公眾號(hào):bigsai 關(guān)注后回復(fù) java 有精選資料一份!

      Redis Spring Spring Boot

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:《基于Unity與SteamVR構(gòu)建虛擬世界》 —2.1.3 Rift推薦規(guī)格
      下一篇:excel使用求和公式的方法
      相關(guān)文章
      亚洲AV无码乱码在线观看裸奔| 亚洲AV无码成人精品区狼人影院 | 亚洲精品乱码久久久久久按摩| 亚洲av无码成人影院一区| 学生妹亚洲一区二区| 亚洲女人影院想要爱| 久久亚洲AV成人无码| 久久久久久亚洲精品成人| 亚洲va在线va天堂va888www| 亚洲AV无码乱码国产麻豆穿越| 亚洲综合伊人久久大杳蕉| 亚洲日本一区二区三区在线不卡| 亚洲av永久中文无码精品综合 | 亚洲AV成人无码天堂| 亚洲另类视频在线观看| 亚洲制服丝袜在线播放| 亚洲成a人片在线不卡| 国产成人精品日本亚洲专区6| 麻豆狠色伊人亚洲综合网站 | 亚洲精品国产福利一二区| 国产亚洲视频在线观看网址| 国产亚洲综合精品一区二区三区| 国产精品亚洲综合天堂夜夜| 国产精品亚洲专区无码不卡| 国产亚洲人成在线影院| 亚洲阿v天堂在线2017免费| 国产精品V亚洲精品V日韩精品 | 亚洲精品NV久久久久久久久久| 亚洲精品NV久久久久久久久久| 久久精品夜色噜噜亚洲A∨| 亚洲夜夜欢A∨一区二区三区 | 亚洲综合精品香蕉久久网| 精品久久久久久亚洲| 亚洲人成网址在线观看 | 亚洲国产精品国产自在在线| 亚洲国产日韩成人综合天堂| 精品国产香蕉伊思人在线在线亚洲一区二区 | 亚洲精品亚洲人成人网| 亚洲AV永久无码区成人网站| 亚洲图片在线观看| 亚洲av片不卡无码久久|