Spring Boot整合@Cacheable注解使用 --解决商品详情信息

 

在电商行业中,解决订单数据量的问题,就是利用es 通过logstash读取,订单展示解决,商品详情,我们你用,缓存技术实现。目前最多的实现技术,就是redis技术,今天我们你用spring的cache缓存技术来实现商品详情信息,缓存使用,解决,商品详情加载慢的情况,

 

 

直接上代码:

SpringCacheConfig

package com.hbg.common.cache;

import com.hbg.common.constants.RedisKeyConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * @author huojg
 * @date 2020/11/5 16:49
 */
@Configuration
@EnableCaching
public class SpringCacheConfig extends CachingConfigurerSupport {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private CacheManager goodsDetailCacheManager;

    @Autowired
    private CacheManager defaultCacheManager;

    @Bean(name = "goodsCacheResolver")
    public CacheResolver goodsCacheResolver() {
        return new SimpleCacheResolver(goodsDetailCacheManager);
    }

    @Override
    @Bean(name = "defaultCacheResolver")
    public CacheResolver cacheResolver() {
        return new SimpleCacheResolver(defaultCacheManager);
    }

    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
        // 用于捕获从Cache中进行CRUD时的异常的回调处理器。
        return new SimpleCacheErrorHandler();
    }

    /**
     * 自定义生成redis-key
     *
     * @return
     */
/*    @Override
    @Bean
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }*/

    /**
     * 商品详情用的缓存管理器
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public CacheManager goodsDetailCacheManager(RedisConnectionFactory redisConnectionFactory) {
        return this.goodsDetailCacheManager(redisConnectionFactory, 30L);
    }


    @Bean
    public CacheManager defaultCacheManager(RedisConnectionFactory redisConnectionFactory) {
        return this.goodsDetailCacheManager(redisConnectionFactory, 24*60L);
    }

    /**
     * 配置缓存管理器
     * @param redisConnectionFactory
     * @param minutes
     * @return
     */
    private CacheManager goodsDetailCacheManager(RedisConnectionFactory redisConnectionFactory, long minutes) {
        //缓存配置对象
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();

        //设置缓存的默认超时时间:30分钟
        redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(minutes))
                //如果是空值,不缓存
                .disableCachingNullValues()
                //设置key序列化器
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                //设置value序列化器
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));

        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration).build();
    }
}

配置完成以后,如何使用了?

 @Cacheable(cacheNames = RedisKeyConstant.ROOT_VALUE,
            key = "T(com.hbg.common.constants.RedisKeyConstant).annoCachedKey(T(com.hbg.common.constants.RedisKeyConstant).GOODS_DETAIL, #goodsId)",
            cacheResolver = "goodsCacheResolver")
    public GoodsDetailResponse getCachedGoodsDetail(Long goodsId) {
        Goods goods = goodsManager.getById(goodsId);
        Assert.notNull(goods, BusinessErrorEnum.GOODS_NOT_EXIST);
        GoodsDetailResponse goodsDetailResponse = BeanCopyUtil.copyProperties(goods, GoodsDetailResponse.class);
        // 查询 供货商信息
        CompletableFuture<Void> supplierFuture = scheduler.run(() -> {
            if (goods.getSupplierId() != null) {
                Supplier supplier = supplierManager.getById(goods.getSupplierId());
                if (supplier != null) {
                    goodsDetailResponse.setSupplier(BeanCopyUtil.copyProperties(supplier, SupplierResponse.class));
                }
            }
        });
        GoodsExtends goodsExtends = goodsExtendsManager.getByGoodsId(goodsId);
        List<Sku> skuList = skuManager.getByGoodsId(goodsId);

        List<GoodsMaterial> goodsMaterialList = goodsMaterialManager.getByGoodsId(goodsId);

        BeanCopyUtil.copyProperties(goodsExtends, goodsDetailResponse);
        List<SkuResponse> skuResponseList = Lists.newArrayList();
        skuList.forEach(sku -> {
            SkuResponse skuResponse = BeanCopyUtil.copyProperties(sku, SkuResponse.class);
            skuResponse.setSpecValues(sku.getSpecValueList());
            skuResponse.setSkuId(sku.getId());
            skuResponseList.add(skuResponse);

        });
        goodsDetailResponse.setGoodsSpecs(goods.getSpecList());
        goodsDetailResponse.setFreightPrice(this.getGoodsPreViewFreightPrice(goodsExtends));
        goodsDetailResponse.setSkuResponseList(skuResponseList);
        goodsDetailResponse.setGoodsImgUrls(StreamUtil.map(goodsMaterialList, GoodsMaterial::getMeterialUrl));
        goodsDetailResponse.setGoodsImgUrls(goodsMaterialManager.getUrlListByGoodsId(goods.getId()));
        //展示销量 = 虚拟+真实
        GoodsSummary goodsSummary =goodsSummaryManager.getById(goodsId);
        if (goodsSummary != null) {
            goodsDetailResponse.setVirtualSoldCount(goods.getVirtualSoldCount() + goodsSummary.getSaleCount());
        }
        supplierFuture.join();
        return goodsDetailResponse;
    }

 

重点就是注解:

@Cacheable的作用:把方法的返回值添加到Ehcache中做缓存

value属性:指定一个Ehcache配置文件中的缓存策略,如果没有给定value,则使用默认的缓存策略

<!-- 自定义缓存策略 -->
    <cache name="users"
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </cache>

key:给存储值取个名字,如果查询的时候有相同的名称,那么就从缓存中将数据拿出来

@Cacheable 作用:把方法的返回值添加到 Ehcache 中做缓存 Value 属性:指定一个 Ehcache 配置文件中的缓存策略,如果么有给定 value,name 则 表示使用默认的缓存策略

@CacheEvict 作用:清除缓存

@Caching(evict = { @CacheEvict(value = RedisKeyConstant.ROOT_VALUE,
            key = "T(com.hbg.common.constants.RedisKeyConstant).annoCachedKey(T(com.hbg.common.constants.RedisKeyConstant).GOODS_PROFIT_CONFIG, #goodsEditRequest.goodsId)"),
            @CacheEvict(cacheNames= RedisKeyConstant.ROOT_VALUE,
                    key = "T(com.hbg.common.constants.RedisKeyConstant).annoCachedKey(T(com.hbg.common.constants.RedisKeyConstant).GOODS_DETAIL, #goodsEditRequest.goodsId)"),
            @CacheEvict(cacheNames= RedisKeyConstant.ROOT_VALUE,
                    key = "T(com.hbg.common.constants.RedisKeyConstant).annoCachedKey(T(com.hbg.common.constants.RedisKeyConstant).ACT_GOODS_DETAIL, #goodsEditRequest.goodsId)")
    })
    public void editGoods(GoodsEditRequest goodsEditRequest) {

缓存多少到时候就要清除多少。

上面就是商品详情编辑的时候,需要加上清除缓存的作用。

 

实在不知道怎么使用,请联系我,单次服务10元

 

posted @ 2020-11-10 15:57  技术专家  阅读(452)  评论(0)    收藏  举报