最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Spring Cache設(shè)置緩存條件操作

 更新時(shí)間:2021年09月14日 15:56:49   作者:梁云亮  
這篇文章主要介紹了使用Spring Cache設(shè)置緩存條件操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring Cache設(shè)置緩存條件

原理

從Spring3.1開(kāi)始,Spring框架提供了對(duì)Cache的支持,提供了一個(gè)對(duì)緩存使用的抽象,通過(guò)在既有代碼中添加少量它定義的各種 annotation,即能夠達(dá)到緩存方法的返回對(duì)象的作用。

提供的主要注解有@Cacheable、@CachePut、@CacheEvict和@Caching,具體見(jiàn)下表:

注解 說(shuō)明
@Cacheable 可以標(biāo)注在類或方法上:標(biāo)注在方法上表示該方法支持?jǐn)?shù)據(jù)緩存;標(biāo)在類上表示該類的所有方法都支持?jǐn)?shù)據(jù)緩存。 具體功能:在執(zhí)行方法體之前,檢查緩存中是否有相同key值的緩存存在,如果存在對(duì)應(yīng)的緩存,直接返回緩存中的值;如果不存在對(duì)應(yīng)的緩存,則執(zhí)行相應(yīng)的方法體獲取數(shù)據(jù),并將數(shù)據(jù)存儲(chǔ)到緩存中。
@CachePut 可以標(biāo)注在類或方法上,表示支持?jǐn)?shù)據(jù)緩存。 具體功能:在方法執(zhí)行前不會(huì)檢查緩存中是否存在相應(yīng)的緩存,而是每次都會(huì)執(zhí)行方法體,并將方法執(zhí)行結(jié)果存儲(chǔ)到緩存中,如果相應(yīng)key值的緩存存在,則更新key對(duì)應(yīng)的value值。
@CacheEvict 可以標(biāo)注在類或方法上,用于清除相應(yīng)key值的緩存。
@Caching 可以標(biāo)注在類或方法上,它有三個(gè)屬性cacheable、put、evict分別用于指定@Cacheable、@CachePut和@CacheEvict

當(dāng)需要在類上或方法上同時(shí)使用多個(gè)注解時(shí),可以使用@Caching,如:

@Caching(cacheable=@Cacheable("User"), evict = {@CacheEvict("Member"), @CacheEvict(value = "Customer", allEntries = true)})

@Cacheable的常用屬性及說(shuō)明

如下表所示:

@Cacheable屬性 說(shuō)明
key 表示緩存的名稱,必須指定且至少要有一個(gè)值,比如:@Cacheable(value=“Dept”)或@Cacheable(value={“Dept”,“Depts”})
condition 表示是否需要緩存,默認(rèn)為空,表示所有情況都會(huì)緩存。通過(guò)SpEL表達(dá)式來(lái)指定,若condition的值為true則會(huì)緩存,若為false則不會(huì)緩存,如@Cacheable(value=“Dept”,key="‘deptno_'+# deptno “,condition=”#deptno<=40")
value 表示緩存的key,支持SpEL表達(dá)式,如@Cacheable(value=“Dept”,key="‘deptno_' +#deptno"),可以不指定值,如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合。除了上述使用方法參數(shù)作為key之外,Spring還提供了一個(gè)root對(duì)象用來(lái)生成key,使用方法如下表所示,其中"#root"可以省略。

Root對(duì)象

Root對(duì)象 說(shuō)明
methodName 當(dāng)前方法名,比如#root.methodName
method 當(dāng)前方法,比如#root.method.name
target 當(dāng)前被調(diào)用的對(duì)象,比如#root.target
targetClass 當(dāng)前被調(diào)用的對(duì)象的class,比如#root.targetClass
args 當(dāng)前方法參數(shù)組成的數(shù)組,比如#root.args[0]
caches 當(dāng)前被調(diào)用的方法使用的緩存,比如#root.caches[0].name

@CachePut的常用屬性同@Cacheable

@CacheEvict的常用屬性如下表所示:

@CacheEvict屬性 說(shuō)明
value 表示要清除的緩存名
key 表示需要清除的緩存key值,
condition 當(dāng)condition的值為true時(shí)才清除緩存
allEntries 表示是否需要清除緩存中的所有元素。默認(rèn)為false,表示不需要,當(dāng)指定了allEntries為true時(shí),將忽略指定的key。
beforeInvocation 清除操作默認(rèn)是在方法成功執(zhí)行之后觸發(fā)的,即方法如果因?yàn)閽伋霎惓6茨艹晒Ψ祷貢r(shí)不會(huì)觸發(fā)清除操作。使用beforeInvocation可以改變觸發(fā)清除操作的時(shí)間,當(dāng)該屬性值為true時(shí),會(huì)在調(diào)用該方法之前清除緩存中的指定元素。

示例:設(shè)置當(dāng) dname 的長(zhǎng)度大于3時(shí)才緩存

//條件緩存
@ResponseBody
@GetMapping("/getLocByDname")
@Cacheable(cacheNames = "dept", key = "#dname", condition = "#dname.length()>3")
public String getLocByDname(@RequestParam("dname") String dname) {//key動(dòng)態(tài)參數(shù)
    QueryWrapper<Dept> queryMapper = new QueryWrapper<>();
    queryMapper.eq("dname", dname);
    Dept dept = deptService.getOne(queryMapper);
    return dept.getLoc();
}

示例:unless 即條件不成立時(shí)緩存

#result 代表返回值,意思是當(dāng)返回碼不等于 200 時(shí)不緩存,也就是等于 200 時(shí)才緩存。

@ResponseBody
@GetMapping("/getDeptByDname")
@Cacheable(cacheNames = "dept", key = "#dname", unless = "#result.code != 200")
public Result<Dept> getDeptByDname(@RequestParam("dname") String dname){//key動(dòng)態(tài)參數(shù)
    QueryWrapper<Dept> queryMapper = new QueryWrapper<>();
    queryMapper.eq("dname", dname);
    Dept dept = deptService.getOne(queryMapper);
    if (dept == null)
        return ResultUtil.error(120, "dept is null");
    else
        return ResultUtil.success(dept);
}

Cache緩存配置

1、pom.xml

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 反射工具類用于手動(dòng)掃描指定包下的注解,根據(jù)defaultCache模塊增加ehcache緩存域(非Spring Cache必須)-->
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.11</version>
</dependency>

2、Ehcache配置文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!-- 磁盤(pán)緩存位置 -->
    <diskStore path="java.io.tmpdir" />
    <!--
        name:緩存名稱。
        maxElementsInMemory:緩存最大個(gè)數(shù)。
        eternal:對(duì)象是否永久有效,一但設(shè)置了,timeout將不起作用。
        timeToIdleSeconds:設(shè)置對(duì)象在失效前的允許閑置時(shí)間(單位:秒)。僅當(dāng)eternal=false對(duì)象不是永久有效時(shí)使用,可選屬性,默認(rèn)值是0,也就是可閑置時(shí)間無(wú)窮大。
        timeToLiveSeconds:設(shè)置對(duì)象在失效前允許存活時(shí)間(單位:秒)。最大時(shí)間介于創(chuàng)建時(shí)間和失效時(shí)間之間。僅當(dāng)eternal=false對(duì)象不是永久有效時(shí)使用,默認(rèn)是0.,也就是對(duì)象存活時(shí)間無(wú)窮大。
        overflowToDisk:當(dāng)內(nèi)存中對(duì)象數(shù)量達(dá)到maxElementsInMemory時(shí),Ehcache將會(huì)對(duì)象寫(xiě)到磁盤(pán)中。
        diskSpoolBufferSizeMB:這個(gè)參數(shù)設(shè)置DiskStore(磁盤(pán)緩存)的緩存區(qū)大小。默認(rèn)是30MB。每個(gè)Cache都應(yīng)該有自己的一個(gè)緩沖區(qū)。
        maxElementsOnDisk:硬盤(pán)最大緩存?zhèn)€數(shù)。
        diskPersistent:是否緩存虛擬機(jī)重啟期數(shù)據(jù) Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
        diskExpiryThreadIntervalSeconds:磁盤(pán)失效線程運(yùn)行時(shí)間間隔,默認(rèn)是120秒。
        memoryStoreEvictionPolicy:當(dāng)達(dá)到maxElementsInMemory限制時(shí),Ehcache將會(huì)根據(jù)指定的策略去清理內(nèi)存。默認(rèn)策略是LRU(最近最少使用)。你可以設(shè)置為FIFO(先進(jìn)先出)或是LFU(較少使用)。
        clearOnFlush:內(nèi)存數(shù)量最大時(shí)是否清除。
    -->
    <!-- 默認(rèn)緩存 -->
    <defaultCache
            eternal="false"
            maxElementsInMemory="200000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="0"
            timeToLiveSeconds="600"
            memoryStoreEvictionPolicy="LRU" />
</ehcache>

3、配置類

@Configuration
@EnableCaching
public class CustomConfiguration {
    /**
     * @see org.springframework.cache.interceptor.SimpleKeyGenerator
     * Generate a key based on the specified parameters.
     */
    public static Object generateKey(Object... params) {
        if (params.length == 0) {
            return SimpleKey.EMPTY;
        }
        if (params.length == 1) {
            Object param = params[0];
            if (param != null && !param.getClass().isArray()) {
                return param;
            }
        }
        return new SimpleKey(params);
    }
/**
 * 若將target作為key的一部分時(shí),CGLIB動(dòng)態(tài)代理可能導(dǎo)致重復(fù)緩存
 * 注意:返回的key一定要重寫(xiě)hashCode()和toString(),防止key對(duì)象不一致導(dǎo)致的緩存無(wú)法命中
 * 例如:ehcache 底層存儲(chǔ)net.sf.ehcache.store.chm.SelectableConcurrentHashMap#containsKey
 */
    @Bean
    public KeyGenerator customKeyGenerator(){
        return (target, method, params) -> {
            final Object key = generateKey(params);
            StringBuffer buffer = new StringBuffer();
            buffer.append(method.getName());
            buffer.append("::");
            buffer.append(key.toString());
// 注意一定要轉(zhuǎn)為String,否則ehcache key對(duì)象可能不一樣,導(dǎo)致緩存無(wú)法命中
            return buffer.toString();
        };
    }
    /**
     * redis緩存管理器
     */
    @Bean
    @ConditionalOnBean(RedisConfiguration.class)
    @ConditionalOnProperty(prefix = "spring.cache", name = "type", havingValue = "redis",
            matchIfMissing = false)
    public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                .entryTtl(Duration.ofMinutes(10));
        return RedisCacheManager
                .builder(RedisCacheWriter.lockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(config).build();
    }
/**
 * ehcache緩存管理器(默認(rèn))
 * default XML files {@link net.sf.ehcache.config.ConfigurationFactory#parseConfiguration()}
 */
    @Bean
    @ConditionalOnProperty(prefix = "spring.cache", name = "type", havingValue = "ehcache",
            matchIfMissing = true)
    public CacheManager ehcacheCacheManager() {
        net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.create();
        /**
         * 包掃描查找指定注解并將cacheNames添加到net.sf.ehcache.CacheManager(單例)
         */
        Reflections reflections = new Reflections("com.example.demo.service", new TypeAnnotationsScanner()
                , new SubTypesScanner(), new MethodAnnotationsScanner());
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(CacheConfig.class);
        for (Class<?> aClass : classesList) {
            final CacheConfig config = AnnotationUtils.findAnnotation(aClass, CacheConfig.class);
            if (config.cacheNames() != null && config.cacheNames().length > 0) {
                for (String cacheName : config.cacheNames()) {
                    cacheManager.addCacheIfAbsent(cacheName);
                }
            }
        }
        /**
         * 方法級(jí)別的注解 @Caching、@CacheEvict、@Cacheable、@CachePut,結(jié)合實(shí)際業(yè)務(wù)場(chǎng)景僅掃描@Cacheable即可
         */
        final Set<Method> methods = reflections.getMethodsAnnotatedWith(Cacheable.class);
        for (Method method : methods) {
            final Cacheable cacheable = AnnotationUtils.findAnnotation(method, Cacheable.class);
            if (cacheable.cacheNames() != null && cacheable.cacheNames().length > 0) {
                for (String cacheName : cacheable.cacheNames()) {
                    cacheManager.addCacheIfAbsent(cacheName);
                }
            }
        }
        EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager();
        ehCacheCacheManager.setCacheManager(cacheManager);
        return ehCacheCacheManager;
    }
}

4、示例

@Component
@CacheConfig(cacheNames = "XXXServiceImpl", keyGenerator = "customKeyGenerator")
public class XXXServiceImpl extends ServiceImpl<XXXMapper, XXXEntity> implements XXXService {
    @CacheEvict(allEntries = true)
    public void evictAllEntries() {}
    @Override
    @Cacheable
    public List<XXXEntity> findById(Long id) {
        return this.baseMapper.selectList(new QueryWrapper<XXXEntity>().lambda()
                .eq(XXXEntity::getId, id));
    }
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Java動(dòng)態(tài)代理的實(shí)現(xiàn)及應(yīng)用

    詳解Java動(dòng)態(tài)代理的實(shí)現(xiàn)及應(yīng)用

    這篇文章主要介紹了詳解Java動(dòng)態(tài)代理的實(shí)現(xiàn)及應(yīng)用的相關(guān)資料,希望通過(guò)本文大家能理解掌握J(rèn)ava動(dòng)態(tài)代理的使用方法,需要的朋友可以參考下
    2017-09-09
  • String字符串拼接方法concat和+的效率對(duì)比

    String字符串拼接方法concat和+的效率對(duì)比

    這篇文章主要介紹了String字符串拼接方法concat和+的效率對(duì)比,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Spring中自動(dòng)裝配的4種方式

    Spring中自動(dòng)裝配的4種方式

    今天小編就為大家分享一篇關(guān)于Spring中自動(dòng)裝配的4種方式,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Springboot實(shí)現(xiàn)人臉識(shí)別與WebSocket長(zhǎng)連接的實(shí)現(xiàn)代碼

    Springboot實(shí)現(xiàn)人臉識(shí)別與WebSocket長(zhǎng)連接的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Springboot實(shí)現(xiàn)人臉識(shí)別與WebSocket長(zhǎng)連接的實(shí)現(xiàn),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-11-11
  • Java應(yīng)用CPU使用率過(guò)高排查方式

    Java應(yīng)用CPU使用率過(guò)高排查方式

    這篇文章主要介紹了Java應(yīng)用CPU使用率過(guò)高排查方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java圖片處理之獲取gif圖一幀圖片的兩種方法

    Java圖片處理之獲取gif圖一幀圖片的兩種方法

    這篇文章主要給大家介紹了關(guān)于Java圖片處理之獲取gif圖一幀圖片的兩種方法,分別是利用Java原生代碼和使用im4java調(diào)用ImageMagick來(lái)實(shí)現(xiàn),兩種方法都給出來(lái)示例代碼供大家參考學(xué)習(xí),需要的朋友們下面來(lái)一起看看吧。
    2017-10-10
  • 沒(méi)有編輯器的環(huán)境下是如何創(chuàng)建Servlet(Tomcat+Java)項(xiàng)目的?

    沒(méi)有編輯器的環(huán)境下是如何創(chuàng)建Servlet(Tomcat+Java)項(xiàng)目的?

    今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著在沒(méi)有編輯器的環(huán)境下如何創(chuàng)建Servlet(Tomcat+Java)項(xiàng)目展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 持久層ORM框架Hibernate框架的使用及搭建方式

    持久層ORM框架Hibernate框架的使用及搭建方式

    Hibernate是一個(gè)開(kāi)放源代碼的對(duì)象關(guān)系映射框架,它對(duì)JDBC進(jìn)行了非常輕量級(jí)的對(duì)象封裝,使得Java程序員可以隨心所欲的使用對(duì)象編程思維來(lái)操縱數(shù)據(jù)庫(kù),本文重點(diǎn)給大家介紹持久層ORM框架Hibernate框架的使用及搭建方式,感興趣的朋友一起看看吧
    2021-11-11
  • SpringBoot集成Redis及SpringCache緩存管理示例詳解

    SpringBoot集成Redis及SpringCache緩存管理示例詳解

    本文介紹了如何在SpringBoot中集成Redis并使用SpringCache進(jìn)行緩存管理,詳解了Redis的配置、使用以及SpringCache的注解,還闡述了SpringCache的工作原理,包括其AOP實(shí)現(xiàn)和與各種緩存框架的集成,使得開(kāi)發(fā)者可以輕松實(shí)現(xiàn)緩存功能,以提高應(yīng)用性能
    2024-09-09
  • Java線程池的分析和使用詳解

    Java線程池的分析和使用詳解

    本篇文章主要介紹了Java線程池的分析和使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-11-11

最新評(píng)論

淮安市| 德清县| 武冈市| 平安县| 广西| 噶尔县| 安图县| 特克斯县| 黄梅县| 宜兰县| 房山区| 屏山县| 南江县| 象州县| 宽城| 龙里县| 平果县| 康马县| 南宁市| 钟祥市| 河津市| 靖边县| 松阳县| 布尔津县| 湘乡市| 团风县| 银川市| 天等县| 临漳县| 招远市| 西乌珠穆沁旗| 那坡县| 达日县| 黄冈市| 德昌县| 南开区| 徐水县| 西青区| 神池县| 唐河县| 陇西县|