商品详细
一、环境准备
- C:\Windows\System32\drivers\etc\hosts
添加本地域名解析
- 添加nginx配置
/mydata/nginx/conf
docker restart nginx #重启nginx
- 修改gateway网关
- id: nginx_route
uri: lb://achangmall-product
predicates:
- Host=achangmall.com,item.achangmall.com
- 启动nacos
startup.cmd -m standalone #单机启动
- 拉静态文件去product服务,并改名为item.html
- 将静态资源上传至nginx,并创建item文件夹
/mydata/nginx/html/item
- 修改search服务的list.html页面
二、商品详细业务代码
- com.achang.achangmall.product.web.ItemController
@Controller
public class ItemController {
@Autowired
private SkuInfoService skuInfoService;
/**
* 展示当前sku的详细
*/
@GetMapping("/{skuId}.html")
public String skuItem(@PathVariable("skuId") Long skuId, Model model){
SkuItemVo vo = skuInfoService.item(skuId);
model.addAttribute("item",vo);
return "item";
}
}
- com.achang.achangmall.product.service.impl.SkuInfoServiceImpl
@Autowired
private SkuImagesService imagesService;
@Autowired
private SpuInfoDescService spuInfoDescService;
@Autowired
private AttrGroupService attrGroupService;
@Autowired
private SkuSaleAttrValueService skuSaleAttrValueService;
@Override
public SkuItemVo item(Long skuId) {
SkuItemVo skuItemVo = new SkuItemVo();
SkuInfoEntity info = getById(skuId);
Long catalogId = info.getCatalogId();
Long spuId = info.getSpuId();
skuItemVo.setInfo(info);
List<SkuImagesEntity> images = imagesService.getImageBySkuId(skuId);
skuItemVo.setImages(images);
List<SkuItemVo.ItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getAttrsBySpuId(spuId);
skuItemVo.setSaleAttr(saleAttrVos);
SpuInfoDescEntity spuInfoDescServiceById = spuInfoDescService.getById(spuId);
skuItemVo.setDesp(spuInfoDescServiceById);
List<SkuItemVo.SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(spuId,catalogId);
skuItemVo.setGroupAttrs(attrGroupVos);
return skuItemVo;
}
- com.achang.achangmall.product.vo.SkuItemVo
@Data
public class SkuItemVo {
SkuInfoEntity info;
List<SkuImagesEntity> images;
List<ItemSaleAttrVo> saleAttr;
SpuInfoDescEntity desp;
List<SpuItemAttrGroupVo> groupAttrs;
@Data
public static class ItemSaleAttrVo{
private Long attrId;
private String attrName;
private String attrValue;
}
@Data
public static class SpuItemAttrGroupVo{
private String groupName;
private List<SpuBaseAttrVo> attrs;
}
@Data
public static class SpuBaseAttrVo{
private String attrName;
private String attrValue;
}
}
- achangmall-product/src/main/resources/mapper/product/AttrGroupDao.xml
<resultMap id="spuItemAttrGroupVo" type="com.achang.achangmall.product.vo.SkuItemVo$SpuItemAttrGroupVo">
<result property="groupName" column="attr_group_name"></result>
<collection property="attrs" ofType="com.achang.achangmall.product.vo.SkuItemVo$SpuBaseAttrVo">
<result column="attr_name" property="attrName"></result>
<result column="attr_value" property="attrValue"></result>
</collection>
</resultMap>
<select id="getAttrGroupWithAttrsBySpuId"
resultMap="spuItemAttrGroupVo">
select
pav.spu_id,
ag.attr_group_name,
ag.attr_group_id,
attr.attr_id,
attr.attr_name,
pav.attr_value
from pms_attr_group ag
left join pms_attr_attrgroup_relation arr on aar.attr_group_id = ag.attr_group_id
left join pms_attr attr on attr.attr_id = aar.attr_id
left join pms_product_attr_value pav on pav.attr_id = attr.attr_id
where ag.catelog_id = #{catelogId} and pav.spu_id = #{spuId}
</select>
- com.achang.achangmall.product.service.impl.SkuImagesServiceImpl
@Override
public List<SkuImagesEntity> getImageBySkuId(Long skuId) {
return baseMapper.selectList(new QueryWrapper<SkuImagesEntity>().eq("sku_id",skuId));
}
- com.achang.achangmall.product.service.impl.AttrGroupServiceImpl
@Override
public List<SkuItemVo.SpuItemAttrGroupVo> getAttrGroupWithAttrsBySpuId(Long spuId,Long catalogId) {
List<SkuItemVo.SpuItemAttrGroupVo> vos = baseMapper.getAttrGroupWithAttrsBySpuId(spuId,catalogId);
return vos;
}
- com.achang.achangmall.product.service.impl.SkuSaleAttrValueServiceImpl
@Override
public List<SkuItemVo.ItemSaleAttrVo> getAttrsBySpuId(Long spuId) {
List<SkuItemVo.ItemSaleAttrVo> itemSaleAttrVos = baseMapper.getSaleAttrsBySpuId(spuId);
return itemSaleAttrVos;
}
- achangmall-product/src/main/resources/mapper/product/SkuSaleAttrValueDao.xml
<select id="getSaleAttrsBySpuId" resultType="com.achang.achangmall.product.vo.SkuItemVo$ItemSaleAttrVo">
select
ssav.attr_id attr_id,
ssav.attr_name attr_name,
GROUP_CONCAT(DISTINCT ssav.attr_value) attr_values
from pms_sku_info info
left join pms_sku_sale_attr_value ssav on ssav.sku_id = info.sku_id
where info.spu_id = #{spuId}
group by ssav.attr_id , ssav.attr_name
</select>
三、优化:异步编排
通过昨天学习的CompletableFuture, 【 之前的学习笔记总结】
- 业务线程池
com.achang.achangmall.product.conf.ThreadPoolConfig
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
pool.getCoreSize(),
pool.getMaxSize(),
pool.getKeepAliveTime(),
TimeUnit.SECONDS, new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
return threadPoolExecutor;
}
}
- com.achang.achangmall.product.conf.ThreadPoolConfigProperties
@Component
@ConfigurationProperties(prefix = "achangmall.thread")
@Data
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer MaxSize;
private Integer keepAliveTime;
}
- achangmall-product/pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
- achangmall-product/src/main/resources/application.yaml
achangmall:
thread:
core-size: 20
max-size: 200
keep-alive-time: 20
- com.achang.achangmall.product.service.impl.SkuInfoServiceImpl
通过CompletableFuture异步编排
@Autowired
private SkuImagesService imagesService;
@Autowired
private SpuInfoDescService spuInfoDescService;
@Autowired
private AttrGroupService attrGroupService;
@Autowired
private SkuSaleAttrValueService skuSaleAttrValueService;
@Autowired
private ThreadPoolExecutor executor;
@Override
public SkuItemVo item(Long skuId) {
SkuItemVo skuItemVo = new SkuItemVo();
CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
SkuInfoEntity infoEntity = getById(skuId);
skuItemVo.setInfo(infoEntity);
return infoEntity;
}, executor);
CompletableFuture<Void> acceptAsync = infoFuture.thenAcceptAsync(res -> {
List<SkuImagesEntity> images = imagesService.getImageBySkuId(skuId);
skuItemVo.setImages(images);
});
CompletableFuture<Void> voidCompletableFuture = infoFuture.thenAcceptAsync(res -> {
List<SkuItemVo.ItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getAttrsBySpuId(res.getSpuId());
skuItemVo.setSaleAttr(saleAttrVos);
}, executor);
CompletableFuture<Void> completableFuture = infoFuture.thenAcceptAsync(res -> {
SpuInfoDescEntity spuInfoDescServiceById = spuInfoDescService.getById(res.getSkuId());
skuItemVo.setDesp(spuInfoDescServiceById);
}, executor);
CompletableFuture<Void> thenAcceptAsync = infoFuture.thenAcceptAsync(res -> {
List<SkuItemVo.SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
skuItemVo.setGroupAttrs(attrGroupVos);
}, executor);
//等待所有任务都完成
try {
CompletableFuture.allOf(infoFuture,acceptAsync,voidCompletableFuture,completableFuture,thenAcceptAsync).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return skuItemVo;
}