maven整合@data注解_springboot整合spring Cache(redis)
前言
前面有介紹過spring整合redis和redis的一些注意點,在實際開發(fā)中,spring cache方便簡化的緩存操作的大部分內(nèi)容。通過注解的方式實現(xiàn)緩存。
緩存抽象的核心是將緩存應(yīng)用于Java方法,從而根據(jù)緩存中可用的信息減少執(zhí)行次數(shù)。也就是說,每次調(diào)用目標(biāo)方法時,抽象都會應(yīng)用一種緩存行為,該行為檢查該方法是否已針對給定參數(shù)執(zhí)行。
- 如果已執(zhí)行,則返回緩存的結(jié)果,而不必執(zhí)行實際方法。
- 如果該方法尚未執(zhí)行,則執(zhí)行該方法,并將結(jié)果緩存并返回給用戶,以便下次調(diào)用該方法時,返回緩存的結(jié)果。
- 這樣,對于給定的一組參數(shù),昂貴的方法(無論是CPU還是IO)只能執(zhí)行一次,并且重用結(jié)果而不必再次實際執(zhí)行該方法。
在緩存框架出現(xiàn)之前,要么公司自己寫緩存框架造輪子,要么在每個service中手動修改調(diào)用redis進(jìn)行存儲或者更新(刪除).一旦業(yè)務(wù)邏輯代碼有變,將造成不小的維護(hù)負(fù)擔(dān)。并且代碼量也很大,使得項目看起來很臃腫!
而spring cache的出現(xiàn)用于簡化對緩存的操作,你只需要配置緩存的cacheManager,然后按照一些簡單的序列化配置,在service層即可使用注解的形式對項目邏輯無侵入的調(diào)用緩存。
方法介紹
@Cacheable:
觸發(fā)??緩存填充。即:如果有緩存從緩存中直接拿數(shù)據(jù)(就不走service了),如果沒緩存那么就執(zhí)行service。將service中的值傳到緩存中(執(zhí)行service)。
多個名稱:緩存可能有一個名字或者多個名字,那么你可以@Cacheable("books")或者@Cacheable({"books", "isbns"})表示。
自定義key:大家對同一個接口進(jìn)行查詢,可能有多個參數(shù),那么你可以自定義key。類似@Cacheable(value = "getuser",key = "#username")這樣寫法,這個規(guī)則和mybatis注解很像,但也有點區(qū)別也可以自行拼湊。
條件緩存:有些數(shù)據(jù)你若不想所有都想走緩存,當(dāng)然也可以設(shè)置條件緩存,比如你若想讓兩個字的姓名緩存,那么你可以@Cacheable(value = "getuser",key = "#username",condition="#username.length() < 3")這樣寫法
上鎖:@Cacheable(value = "getuser",key = "#username",sync = true)對有些數(shù)據(jù),你可能不想讓他并發(fā)執(zhí)行,那么可以假設(shè)sync關(guān)鍵字。當(dāng)然,如果是分布式或者多臺服務(wù)器需要考慮分布式鎖實現(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;
}
@CacheEvict:
觸發(fā)??緩存逐出。即刪除緩存。執(zhí)行之后將刪除緩存。
用法和前面相似@CacheEvict(value = "getuser",key = "#username")
- 但是若想刪除getuser下所有緩存目錄,那么加個參數(shù)@CacheEvict(value = "getuser",key = "#username",allEntries = true)其中allEntries就是刪除所有的意思。當(dāng)需要清除整個緩存區(qū)域時,此選項會派上用場。而不是逐出每個條目。
@CachePut:
更新緩存而不會干擾方法執(zhí)行。即:不管有沒有緩存。每次都執(zhí)行方法,將方法得到的數(shù)據(jù)更新到緩存之中。起到update的功能。
需要注意的是,在更新過程中可能有并發(fā)的存在。你可以設(shè)置鎖.參考Cacheable用法
@Caching:
重新組合要應(yīng)用于方法的多個緩存操作。
有時,需要指定相同類型(例如@CacheEvict或 @CachePut)的多個注釋- 例如,因為不同高速緩存之間的條件或鍵表達(dá)式不同。@Caching允許多個嵌套 @Cacheable,@CachePut和@CacheEvict注解相同的方法來使用。以下示例使用兩個@CacheEvict注釋:
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
此操作可能是一個方法操作更新、刪除不同的緩存。具體使用需要考慮情景。
@CacheConfig:
在類級別共享一些常見的緩存相關(guān)設(shè)置。
此方法針對同一個類中一些共同操作,簡便操作和代碼量。
到目前為止,我們已經(jīng)看到緩存操作提供了許多自定義選項,您可以為每個操作設(shè)置這些選項。但是,如果某些自定義選項適用于該類的所有操作,則它們可能會很繁瑣。例如,指定用于類的每個高速緩存操作的高速緩存的名稱可以由單個類級定義替換。這是@CacheConfig 發(fā)揮作用的地方。以下示例用于@CacheConfig設(shè)置緩存的名稱:
@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {
@Cacheable
public Book findBook(ISBN isbn) {...}
}
具體整合
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
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
step4: config目錄下建立配置文件(緩存注入對象配置,以及序列化相關(guān)配置,和前文redis差不多)
- 這里面需要注意的是里面有關(guān)于redis的一些配置。在項目中防止多個項目公用一個redis可以在redis前面加個前綴(通常是項目名)。
- 過期時間一定要設(shè)置,并且過期策略還需要根據(jù)項目需求具體踩坑設(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è)置過期時間
.disableCachingNullValues()
.computePrefixWith(cacheName -> "rediscache".concat(":").concat(cacheName).concat(":"))//rediscache可以改成你的項目名
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfiguration)
.build();
}
}
step5:創(chuàng)建pojo對象和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;
}
}
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è)更新用戶賬號密碼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 "移除成功";
}
}
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);
}
}
step6:在啟動類加上允許緩存注解
測試與總結(jié)
getalluser:
getuser:
update:更新上一條
delete:整個移除(前面講到allentries參數(shù)作用,不妨自己測試)
可以看得到緩存的一些操作正常完成了
上文只是一個簡單的整合過程,具體使用還需要自己踩坑才行。而緩存的深度遠(yuǎn)遠(yuǎn)不是這么簡單,還需要自己挖掘。
看完的朋友 求點贊!求轉(zhuǎn)發(fā)!求關(guān)注!
另外需要Java/架構(gòu)的學(xué)習(xí)資料學(xué)習(xí)的朋友可以看一下我的其他文章,可結(jié)合自身情況有選擇下方資料:
全網(wǎng)最新架構(gòu)實戰(zhàn)文檔:高并發(fā)+分布式+微服務(wù)+SpringBoot+Nginx
SB+SC+Nginx+Docker+分布式 2020最新實戰(zhàn)文檔PDF
2020最新一線大廠名企面試題大全
除此之外小編搜集整理一份Java核心知識點:其中包含有基礎(chǔ)知識、Java集合、JVM、多線程并發(fā)、spring原理、微服務(wù)、Netty 與RPC 、Kafka、日記、設(shè)計模式、Java算法、數(shù)據(jù)庫、Zookeeper、分布式緩存、數(shù)據(jù)結(jié)構(gòu)等等
每篇文章下方都有領(lǐng)取方式,歡迎獲取! 注意:免費(fèi)分享!
總結(jié)
以上是生活随笔為你收集整理的maven整合@data注解_springboot整合spring Cache(redis)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tia v15 添加项目_作为一名机器人
- 下一篇: IDEA 点击进入方法内部_【推荐收藏】