谷粒商城 高级篇 (十四) ---------- 商品详情


一、详情数据

在这里插入图片描述
封装成 vo 如下:

SkuItemVo:

@Data
public class SkuItemVo {
    //1、sku基本信息获取  pms_sku_info
    SkuInfoEntity info;

    boolean hasStock = true;

    //2、sku的图片信息  pms_sku_images
    List<SkuImagesEntity> images;

    //3、获取spu的销售属性组合。
    List<SkuItemSaleAttrVo> saleAttr;

    //4、获取spu的介绍
    SpuInfoDescEntity desp;

    //5、获取spu的规格参数信息。
    List<SpuItemAttrGroupVo> groupAttrs;

    SeckillInfoVo seckillInfo;//当前商品的秒杀优惠信息

}

SkuItemSaleAttrVo:

package com.fancy.gulimall.product.vo;

import lombok.Data;
import lombok.ToString;

import java.util.List;

@ToString
@Data
public class SkuItemSaleAttrVo {
    private Long attrId;
    private String attrName;
    private List<AttrValueWithSkuIdVo> attrValues;
}

SpuItemAttrGroupVo:

package com.fancy.gulimall.product.vo;

import lombok.Data;
import lombok.ToString;

import java.util.List;


@Data
@ToString
public class SpuItemAttrGroupVo {

    private String groupName;

    private List<Attr> attrs;

}

二、查询详情

优化方面采用异步编排,要使用异步的话,首先我们需要自定义线程池。。。

package com.fancy.gulimall.product.config;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
        return new ThreadPoolExecutor(
                pool.getCoreSize(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
    }

}

要想实现从 application.properties 中获取数据,我们需要创建一个配置文件

package com.fancy.gulimall.product.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;


@ConfigurationProperties(prefix = "gulimall.thread")
// @Component
@Data
public class ThreadPoolConfigProperties {

    private Integer coreSize;

    private Integer maxSize;

    private Integer keepAliveTime;


}

提示要导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

相应的值在 application.properties 中配置与取出

#配置线程池
gulimall.thread.coreSize=20
gulimall.thread.maxSize=200
gulimall.thread.keepAliveTime=10

商品详情的请求:

package com.fancy.gulimall.product.web;

import com.fancy.gulimall.product.service.SkuInfoService;
import com.fancy.gulimall.product.vo.SkuItemVo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import javax.annotation.Resource;
import java.util.concurrent.ExecutionException;

@Controller
public class ItemController {

    @Resource
    private SkuInfoService skuInfoService;

    /**
     * 展示当前sku的详情
     * @param skuId
     * @return
     */
    @GetMapping("/{skuId}.html")
    public String skuItem(@PathVariable("skuId") Long skuId, Model model) throws ExecutionException, InterruptedException {

        System.out.println("准备查询" + skuId + "详情");

        SkuItemVo vos = skuInfoService.item(skuId);
        
        model.addAttribute("item",vos);

        return "item";
    }
}

相应的处理方法:采用异步编排

@Override
public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {
	SkuItemVo skuItemVo = new SkuItemVo();
	CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() ->{
		//1、sku 基本信息获取 pms_sku_info
		SkuInfoEntity info = getById(skuId);
		skuItemVo.setInfo(info);
		return info;
	}, executor);
	CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync((res) -> {
		//3、获取 spu 的销售属性组合。
		List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrsBySpuId(res.getSpuId());
		skuItemVo.setSaleAttr(saleAttrVos);
	}, executor);
	CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync(res -> {
		//4、获取 spu 的介绍 pms_spu_info_desc
		SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
		skuItemVo.setDesp(spuInfoDescEntity);
	}, executor);
	CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync(res -> {
		//5、获取 spu 的规格参数信息。
		List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), 			res.getCatalogId());
		skuItemVo.setGroupAttrs(attrGroupVos);
	}, executor);
	//2、sku 的图片信息 pms_sku_images
	CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
		List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId);
		skuItemVo.setImages(images);
	}, executor);
    //等到所有任务都完成
	CompletableFuture.allOf(saleAttrFuture,descFuture,baseAttrFuture,imageFuture).get();
	return skuItemVo;
}

getSaleAttrsBySpuId 方法的实现:

@Override
 public List<SkuItemSaleAttrVo> getSaleAttrBySpuId(Long spuId) {

     SkuSaleAttrValueDao baseMapper = this.getBaseMapper();
     List<SkuItemSaleAttrVo> saleAttrVos = baseMapper.getSaleAttrBySpuId(spuId);

     return saleAttrVos;
 }

baseMapper.getSaleAttrBySpuId 对应的 mapper 映射文件中方法如下:

<resultMap id="spuAttrGroup" type="com.fancy.gulimall.product.vo.SpuItemAttrGroupVo">
    <result property="groupName" column="attr_group_name"/>
    <collection property="attrs" ofType="com.xunqi.gulimall.product.vo.Attr">
        <result property="attrId" column="attr_id"></result>
        <result property="attrName" column="attr_name"></result>
        <result property="attrValue" column="attr_value"></result>
   </collection>
</resultMap>

<select id="getAttrGroupWithAttrsBySpuId" resultMap="spuAttrGroup">
    SELECT
        product.spu_id,
        pag.attr_group_id,
        pag.attr_group_name,
        product.attr_id,
        product.attr_name,
        product.attr_value
    FROM
        pms_product_attr_value product
            LEFT JOIN pms_attr_attrgroup_relation paar ON product.attr_id = paar.attr_id
            LEFT JOIN pms_attr_group pag ON paar.attr_group_id = pag.attr_group_id
    WHERE
        product.spu_id = #{spuId}
        AND pag.catelog_id = #{catalogId}

</select>

getAttrGroupWithAttrsBySpuId 方法的实现:

@Override
public List<SpuItemAttrGroupVo> getAttrGroupWithAttrsBySpuId(Long spuId, Long catalogId) {

    //1、查出当前spu对应的所有属性的分组信息以及当前分组下的所有属性对应的值
    AttrGroupDao baseMapper = this.getBaseMapper();
    List<SpuItemAttrGroupVo> vos = baseMapper.getAttrGroupWithAttrsBySpuId(spuId,catalogId);

    return vos;
}

getImagesBySkuId 方法的实现:

@Override
public List<SkuImagesEntity> getImagesBySkuId(Long skuId) {

    List<SkuImagesEntity> imagesEntities = this.baseMapper.selectList(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuId));

    return imagesEntities;
}

三、sku 组合切换

页面遍历
<div class="box-attr clear" th:each="attr:${item.saleAttr}">
	<dl>
		<dt>选择[[${attr.attrName}]]</dt>
		<dd th:each="vals:${attr.attrValues}">
			<a class="sku_attr_value" th:attr="skus=${vals.skuIds},class=${#lists.contains(#strings.listSplit(vals.skuIds,','), item.info.skuId.toString())?'sku_attr_value checked':'sku_attr_value'}" >
				[[${vals.attrValue}]]
			<!-- <img src="/static/item/img/59ddfcb1Nc3edb8f1.jpg" /> -->
			</a>
		</dd>
	</dl>
</div>
动态切换
$(".sku_attr_value").click(function(){
	//1、点击的元素先添加上自定义的属性。为了识别我们是刚才被点击的var skus = new Array();
	$(this).addClass("clicked");
	var curr = $(this).attr("skus").split(",");
	//当前被点击的所有 sku 组合数组放进去
	skus.push(curr);
	//去掉同一行的所有的 checked
	$(this).parent().parent().find(".sku_attr_value").removeClass("checked");
	$("a[class='sku_attr_value checked']").each(function(){
		skus.push($(this).attr("skus").split(","));
	});
	console.log(skus);
	//2、取出他们的交集,得到 skuId
	var filterEle = skus[0];
	for(var i = 1;i<skus.length;i++){
		filterEle = $(filterEle).filter(skus[i]);
	}
	console.log(filterEle[0]);
	location.href = "http://item.gulimall.com/"+filterEle[0]+".html";
	//4、跳转
});

四、关键 SQL

SELECT
	ssav.`attr_id` attr_id,
	ssav.`attr_name` attr_name,
	ssav.`attr_value`,
	GROUP_CONCAT(DISTINCT info.`sku_id`) sku_ids
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`,ssav.`attr_value`

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
gulimall_pms 商品 drop table if exists pms_attr; drop table if exists pms_attr_attrgroup_relation; drop table if exists pms_attr_group; drop table if exists pms_brand; drop table if exists pms_category; drop table if exists pms_category_brand_relation; drop table if exists pms_comment_replay; drop table if exists pms_product_attr_value; drop table if exists pms_sku_images; drop table if exists pms_sku_info; drop table if exists pms_sku_sale_attr_value; drop table if exists pms_spu_comment; drop table if exists pms_spu_images; drop table if exists pms_spu_info; drop table if exists pms_spu_info_desc; /*==============================================================*/ /* Table: pms_attr */ /*==============================================================*/ create table pms_attr ( attr_id bigint not null auto_increment comment '属性id', attr_name char(30) comment '属性名', search_type tinyint comment '是否需要检索[0-不需要,1-需要]', icon varchar(255) comment '属性图标', value_select char(255) comment '可选值列表[用逗号分隔]', attr_type tinyint comment '属性类型[0-销售属性,1-基本属性,2-既是销售属性又是基本属性]', enable bigint comment '启用状态[0 - 禁用,1 - 启用]', catelog_id bigint comment '所属分类', show_desc tinyint comment '快速展示【是否展示在介绍上;0-否 1-是】,在sku中仍然可以调整', primary key (attr_id) ); alter table pms_attr comment '商品属性'; /*==============================================================*/ /* Table: pms_attr_attrgroup_relation */ /*==============================================================*/ create table pms_attr_attrgroup_relation ( id bigint not null auto_increment comment 'id', attr_id bigint comment '属性id', attr_group_id bigint comment '属性分组id', attr_sort int comment '属性组内排序', primary key (id) ); alter table pms_attr_attrgroup_relation comment '属性&
根据引用中提供的信息,谷粒商城是一个B2C模式的电商平台,主要销售自营商品给客户。B2C模式指的是商对客的模式,即商家直接向消费者销售商品和服务。谷粒商城使用微服务架构,这是一种将应用程序拆分成独立且可独立开发、部署和扩展的小型服务的架构。引用还提到谷粒商城的技术涵盖微服务架构、分布式、全栈、集群、部署和自动化运维等方面。 因此,从前慢-谷粒商城章6主要讨论的可能是谷粒商城的技术方面,包括微服务架构、分布式、全栈、集群、部署和自动化运维等内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [从前慢-谷粒商城章1](https://blog.csdn.net/m0_67391121/article/details/125383572)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [2020年谷粒商城md笔记](https://download.csdn.net/download/ZHUXIUQINGIT/12543161)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在森林中麋了鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值