mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-23 05:00:25 +08:00
feat(PmsConstants.java): 商品详情缓存
1、添加商品详情本地缓存 2、商品详情分布式锁保证原子操作 Closes I3V770
This commit is contained in:
parent
17dc8fdb59
commit
05dd9a07bf
@ -9,4 +9,8 @@ public interface PmsConstants {
|
|||||||
String LOCKED_STOCK_PREFIX = "stock:locked:";
|
String LOCKED_STOCK_PREFIX = "stock:locked:";
|
||||||
|
|
||||||
String LOCK_SKU_PREFIX="lock:sku:";
|
String LOCK_SKU_PREFIX="lock:sku:";
|
||||||
|
|
||||||
|
String PRODUCT_DETAIL_CACHE = "product:detail:cache:";
|
||||||
|
|
||||||
|
String LOCK_PRODUCT_DETAIL="lock:product:detail";
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.youlai.mall.pms.config;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author DaniR
|
||||||
|
* @version 1.0
|
||||||
|
* @description 本地缓存设置
|
||||||
|
* @createDate 2021/6/16 10:08
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class ProductLocalCache {
|
||||||
|
private Cache<String, ProductFormDTO> localCache = null;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
private void init(){
|
||||||
|
localCache = CacheBuilder.newBuilder()
|
||||||
|
//设置本地缓存容器的初始容量
|
||||||
|
.initialCapacity(10)
|
||||||
|
//设置本地缓存的最大容量
|
||||||
|
.maximumSize(500)
|
||||||
|
//设置写缓存后多少秒过期
|
||||||
|
.expireAfterWrite(60, TimeUnit.SECONDS).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setLocalCache(String key, ProductFormDTO object){
|
||||||
|
localCache.put(key,object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductFormDTO get(String key){
|
||||||
|
return localCache.getIfPresent(key);
|
||||||
|
}
|
||||||
|
}
|
@ -5,58 +5,103 @@ import cn.hutool.core.util.StrUtil;
|
|||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.youlai.common.redis.utils.RedisUtils;
|
||||||
|
import com.youlai.mall.pms.config.ProductLocalCache;
|
||||||
import com.youlai.mall.pms.mapper.PmsSpuMapper;
|
import com.youlai.mall.pms.mapper.PmsSpuMapper;
|
||||||
|
import com.youlai.mall.pms.pojo.dto.SpuDTO;
|
||||||
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
||||||
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
|
||||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||||
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
||||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||||
import com.youlai.mall.pms.pojo.dto.SpuDTO;
|
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
||||||
import com.youlai.mall.pms.service.IPmsSpuAttributeValueService;
|
|
||||||
import com.youlai.mall.pms.service.IPmsSkuService;
|
import com.youlai.mall.pms.service.IPmsSkuService;
|
||||||
import com.youlai.mall.pms.service.IPmsSpecService;
|
import com.youlai.mall.pms.service.IPmsSpecService;
|
||||||
|
import com.youlai.mall.pms.service.IPmsSpuAttributeValueService;
|
||||||
import com.youlai.mall.pms.service.IProductService;
|
import com.youlai.mall.pms.service.IProductService;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.redisson.api.RLock;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.youlai.mall.pms.common.constant.PmsConstants.LOCK_PRODUCT_DETAIL;
|
||||||
|
import static com.youlai.mall.pms.common.constant.PmsConstants.PRODUCT_DETAIL_CACHE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author haoxr
|
* @author haoxr
|
||||||
* @date 2020-11-06
|
* @date 2020-11-06
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@Slf4j
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ProductServiceImpl extends ServiceImpl<PmsSpuMapper, PmsSpu> implements IProductService {
|
public class ProductServiceImpl extends ServiceImpl<PmsSpuMapper, PmsSpu> implements IProductService {
|
||||||
|
|
||||||
private IPmsSkuService iPmsSkuService;
|
private final IPmsSkuService iPmsSkuService;
|
||||||
private IPmsSpuAttributeValueService iPmsSpuAttributeValueService;
|
private final IPmsSpuAttributeValueService iPmsSpuAttributeValueService;
|
||||||
private IPmsSpecService iPmsSpecService;
|
private final IPmsSpecService iPmsSpecService;
|
||||||
|
private final RedisUtils redisUtils;
|
||||||
|
private final RedissonClient redissonClient;
|
||||||
|
private final ProductLocalCache productLocalCache;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProductFormDTO getProductById(Long spuId) {
|
public ProductFormDTO getProductById(Long spuId) {
|
||||||
// spu
|
//1、一级本地缓存设置
|
||||||
PmsSpu spu = this.getById(spuId);
|
ProductFormDTO product = productLocalCache.get(PRODUCT_DETAIL_CACHE + spuId);
|
||||||
SpuDTO SpuDTO = new SpuDTO();
|
if (null != product) {
|
||||||
BeanUtil.copyProperties(spu, SpuDTO);
|
log.info("get LocalCache product:" + product);
|
||||||
if (StrUtil.isNotBlank(spu.getPics())) {
|
return product;
|
||||||
// spu专辑图片转换处理 json字符串 -> List
|
|
||||||
List<String> pics = JSONUtil.toList(JSONUtil.parseArray(spu.getPics()), String.class);
|
|
||||||
SpuDTO.setPics(pics);
|
|
||||||
}
|
}
|
||||||
// 属性
|
//2、二级缓存设置,Redis中获取商品详情信息
|
||||||
List<PmsSpuAttributeValue> attrs = iPmsSpuAttributeValueService.list(
|
product = (ProductFormDTO) redisUtils.get(PRODUCT_DETAIL_CACHE + spuId);
|
||||||
new LambdaQueryWrapper<PmsSpuAttributeValue>(
|
if (null != product) {
|
||||||
).eq(PmsSpuAttributeValue::getSpuId, spuId)
|
log.info("get redis product:" + product);
|
||||||
);
|
return product;
|
||||||
|
}
|
||||||
|
//3、分布式锁,保证原子操作
|
||||||
|
RLock lock = redissonClient.getLock(LOCK_PRODUCT_DETAIL + spuId);
|
||||||
|
try {
|
||||||
|
if (lock.tryLock()) {
|
||||||
|
// spu
|
||||||
|
PmsSpu spu = this.getById(spuId);
|
||||||
|
SpuDTO SpuDTO = new SpuDTO();
|
||||||
|
BeanUtil.copyProperties(spu, SpuDTO);
|
||||||
|
if (StrUtil.isNotBlank(spu.getPics())) {
|
||||||
|
// spu专辑图片转换处理 json字符串 -> List
|
||||||
|
List<String> pics = JSONUtil.toList(JSONUtil.parseArray(spu.getPics()), String.class);
|
||||||
|
SpuDTO.setPics(pics);
|
||||||
|
}
|
||||||
|
// 属性
|
||||||
|
List<PmsSpuAttributeValue> attrs = iPmsSpuAttributeValueService.list(
|
||||||
|
new LambdaQueryWrapper<PmsSpuAttributeValue>(
|
||||||
|
).eq(PmsSpuAttributeValue::getSpuId, spuId)
|
||||||
|
);
|
||||||
|
// 规格
|
||||||
|
List<PmsSpec> specs = iPmsSpecService.listBySpuId(spuId);
|
||||||
|
// sku
|
||||||
|
List<PmsSku> skuList = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, spuId));
|
||||||
|
|
||||||
// 规格
|
product = new ProductFormDTO(SpuDTO, attrs, specs, skuList);
|
||||||
List<PmsSpec> specs = iPmsSpecService.listBySpuId(spuId);
|
//TODO 4、需要判断商品是否是秒杀商品,根据秒杀信息更新商品秒杀相关信息
|
||||||
|
log.info("get db product:" + product);
|
||||||
// sku
|
redisUtils.set(PRODUCT_DETAIL_CACHE + spuId, product, 3600);
|
||||||
List<PmsSku> skuList = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, spuId));
|
productLocalCache.setLocalCache(PRODUCT_DETAIL_CACHE + spuId,product);
|
||||||
|
} else {
|
||||||
ProductFormDTO product = new ProductFormDTO(SpuDTO, attrs, specs, skuList);
|
log.info("get redis2 product:" + product);
|
||||||
|
product = (ProductFormDTO) redisUtils.get(PRODUCT_DETAIL_CACHE + spuId);
|
||||||
|
if (null!=product) {
|
||||||
|
productLocalCache.setLocalCache(PRODUCT_DETAIL_CACHE + spuId, product);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (lock.isLocked()) {
|
||||||
|
if (lock.isHeldByCurrentThread()) {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user