• 尚品汇_第6章_商品详情页


    尚品汇_第6章_商品详情页

    文章目录

    一、商品详情相关业务介绍

    	商品详情页,简单说就是以购物者的角度展现一个sku的详情信息。
    	用户点击不同的销售属性值切换不同的商品
    	点击添加购物车,将商品放入购物车列表中
    
    • 1
    • 2
    • 3

    二、模板技术Thymeleaf介绍

    2.1 Thymeleaf 简介

    Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP,Velocity,FreeMaker等, 它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。与其它模板引擎相比, Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用!

    2.2 快速入门

    项目创建,依赖模块web,Thymeleaf.模板。

    在这里插入图片描述

    2.2.1 设置头文件

    就想Jsp的<%@Page %>一样 ,Thymeleaf的也要引入标签规范。不加这个虽然不影响程序运行,但是你的idea会认不出标签,不方便开发。

    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    
    • 1

    2.2.2 赋值字符串拼接

    request.setAttribute("name","刘德华");
    <p th:text="’hello’ + ${name}" th:value="${name}">p>
    
    • 1
    • 2

    2.2.3 循环

    List<String> list = Arrays.asList("郑爽", "刘德华", "张惠妹", "成龙");
    
    request.setAttribute("arrayList",list);
    
    
    <table>
        
        <tr th:each="s,stat: ${arrayList}">
            <td th:text="${s}">td>
            <td th:text="${stat.index}">td>
            <td th:text="${stat.count}">td>
            <td th:text="${stat.size}">td>
            <td th:text="${stat.even}">td>
            <td th:text="${stat.odd}">td>
            <td th:text="${stat.first}">td>
            <td th:text="${stat.last}">td>
        tr>
    table>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    stat 称作状态变量,属性有
    index:当前迭代对象的 index(从 0 开始计算)
    count:当前迭代对象的 index(从 1 开始计算)
    size:被迭代对象的大小
    even/odd:布尔值,当前循环是否是偶数/奇数
    first:布尔值,当前循环是否是第一个
    last:布尔值,当前循环是否是最后一个
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.2.4 判断

    th:if 条件成立显示

    th:unless 条件不成立的时候才会显示内容

    model.addAttribute("age",18);
    <h2>判断 ifh2>
    <div th:if="${age}>=18" th:text="success">gooddiv>
    <a th:unless="${age != 18}" th:text="success" >atguigua>
    <h2>判断 三元h2>
    <div th:text="${age}>=18?'success':'failure'">div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.2.5 取session中的属性

    httpSession.setAttribute("addr","北京中南海");
    <div th:text="${session.addr}"> div>
    
    • 1
    • 2

    2.2.6 引用内嵌页

    <div th:include="itemInner"/>
    
    • 1

    2.2.7 th:utext :解析样式

    th:utext:识别html中的标签

    request.setAttribute("gname","<span style=color:green>绿色span>");
    <p th:utext="${gname}">colorp>
    
    • 1
    • 2

    2.2.8 点击链接传值

    点我带你飞
    
    • 1
    @RequestMapping("list.html")
    @ResponseBody
    public String list(String category1Id){
        // 接收传递过来的数据
        System.out.println("获取到的数据:\t"+category1Id);
        return category1Id;
    }
    在index 控制器中先存储一个category1Id
    /*保存 category1Id*/
    request.setAttribute("category1Id","2");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.2.9 多种存储方式

    model.addAttribute("addr","北京昌平区");
    hashMap.put("id","101");
    
    HashMap<String, Object> map = new HashMap<>();
    map.put("stuNo","1000");
    map.put("stuName","张三");
    model.addAllAttributes(map);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    <h2> 多种方式存储数据1 h2>
    
    <div th:text="${addr}">div>
    <div th:text="${id}">div>
    
    <h2> 多种方式存储数据2 h2>
    
    <div th:text="${stuNo}">div>
    <div th:text="${stuName}">div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    三、商品详情业务需求分析

    3.1 详情渲染功能介绍

    在这里插入图片描述

    商品详情所需构建的数据如下:
    1,Sku基本信息
    2,Sku图片信息
    3,Sku分类信息
    4,Sku销售属性相关信息
    5,Sku价格信息(平台可以单独修改价格,sku后续会放入缓存,为了回显最新价格,所以单独获取)
    6,展示商品的海报
    7,获取skuId 对应的商品规格参数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    
    
    • 1

    3.2 详情模块规划

    模块规划思路:

    1,service-item微服务模块封装详情页面所需数据接口;
    2,service-item通过feign client调用其他微服务数据接口进行数据汇总;
    3,pc端前台页面通过web-all调用service-item数据接口渲染页面;
    4,service-item可以为pc端、H5、安卓与ios等前端应用提供数据接口,web-all为pc端页面渲染形式
    5,service-item获取商品信息需要调用service-product服务sku信息等;
    6,由于service各微服务可能会相互调用,调用方式都是通过feign client调用,所以我们把feign client api接口单独封装出来,需要时直接引用feign client api模块接口即可,即需创建service-client父模块,管理各service微服务feign client api接口。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    四、商品详情功能开发

    4.1 搭建service-item

    4.1.1 构建模块

    点击service,选择New–>Module,操作如下

    在这里插入图片描述

    下一步

    在这里插入图片描述

    下一步

    在这里插入图片描述

    完成,结构如下
    在这里插入图片描述

    4.1.2 修改配置

    修改配置pom.xml

    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>com.atguigu.gmallgroupId>
            <artifactId>serviceartifactId>
            <version>1.0version>
        parent>
    
        <artifactId>service-itemartifactId>
        <version>1.0version>
    
        <packaging>jarpackaging>
        <name>service-itemname>
        <description>service-itemdescription>
    
    
        <build>
            <finalName>service-itemfinalName>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                plugin>
            plugins>
        build>
    
    project>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    添加配置文件bootstrap.properties

    spring.application.name=service-item
    spring.profiles.active=dev
    spring.cloud.nacos.discovery.server-addr=192.168.200.129:8848
    spring.cloud.nacos.config.server-addr=192.168.200.129:8848
    spring.cloud.nacos.config.prefix=${spring.application.name}
    spring.cloud.nacos.config.file-extension=yaml
    spring.cloud.nacos.config.shared-configs[0].data-id=common.yaml
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    添加启动类

    exclude = DataSourceAutoConfiguration.class 排除数据库链接****jar

    表示当前项目**{service-item}** 不参与数据库查询

    package com.atguigu.gmall.item;
    
    
    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源自动配置
    @ComponentScan({"com.atguigu.gmall"})
    @EnableDiscoveryClient
    @EnableFeignClients(basePackages= {"com.atguigu.gmall"})
    public class ServiceItemApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ServiceItemApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.1.3 service-item服务接口封装

    接口

    package com.atguigu.gmall.item.service;
    
    public interface ItemService {
    
        /**
         * 获取sku详情信息
         * @param skuId
         * @return
         */
        Map<String, Object> getBySkuId(Long skuId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    实现类

    @Service
    public class ItemServiceImpl implements ItemService {
    
        @Override
        public Map<String, Object> getBySkuId(Long skuId) {
            Map<String, Object> result = new HashMap<>();
    
            
            return result;
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    controller

    @RestController
    @RequestMapping("api/item")
    public class ItemApiController {
    
    
        @Autowired
        private ItemService itemService;
    
        /**
         * 获取sku详情信息
         * @param skuId
         * @return
         */
        @GetMapping("{skuId}")
        public Result getItem(@PathVariable Long skuId){
            Map<String,Object> result = itemService.getBySkuId(skuId);
            return Result.ok(result);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    说明:商品详情相关信息在service-product微服务都可以获取,所以我们在service-product模块编写所需要的接口

    service-product模块编写所需要的接口

    4.2 在service-product微服务提供api接口

    4.2.1 获取sku基本信息与图片信息

    4.2.1.1 编写接口与实现类

    ManageService

    接口

    /**
     * 根据skuId 查询skuInfo
     * @param skuId
     * @return
     */
    SkuInfo getSkuInfo(Long skuId);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    实现类

    @Override
    public SkuInfo getSkuInfo(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        // 根据skuId 查询图片列表集合
        QueryWrapper<SkuImage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sku_id", skuId);
        List<SkuImage> skuImageList = skuImageMapper.selectList(queryWrapper);
    
        skuInfo.setSkuImageList(skuImageList);
        return skuInfo;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    4.2.1.2 编写控制器
    package com.atguigu.gmall.product.api.ProductApiController
    @RestController
    @RequestMapping("api/product")
    public class ProductApiController {
    
        @Autowired
        private ManageService manageService;
    
        /**
         * 根据skuId获取sku信息
         * @param skuId
         * @return
         */
        @GetMapping("inner/getSkuInfo/{skuId}")
        public SkuInfo getAttrValueList(@PathVariable("skuId") Long skuId){
            SkuInfo skuInfo = manageService.getSkuInfo(skuId);
            return skuInfo;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4.2.2 获取分类信息

    4.2.2.1 需求分析:

    sku是挂在三级分类下面的,我们的分类信息分别在base_category1、base_category2、base_category3这三张表里面,目前需要通过sku表的三级分类id获取一级分类名称、二级分类名称和三级分类名称

    MySQL 视图(View)是一种虚拟存在的表,同真实表一样,视图也由列和行构成,但视图并不实际存在于数据库中。行和列的数据来自于定义视图的查询中所使用的表,并且还是在使用视图时动态生成的。
    特点:
    数据库中只存放了视图的定义,并没有存放视图中的数据,这些数据都存放在定义视图查询所引用的真实表中。
    
    • 1
    • 2
    • 3

    我们可以建立一个视图****(view),把三张表关联起来,视图id就是三级分类id,这样通过三级分类id就可以查询到相应数据,效果如下:

    在这里插入图片描述

    创建视图
    CREATE VIEW base_category_view AS 
    select  
    c3.id as id,
    c1.id as category1_id, c1.name as category1_name,
    c2.id as category2_id, c2.name as category2_name,
    c3.id as category3_id, c3.name as category3_name
    from base_category1 c1
    inner join base_category2 c2 on c2.category1_id = c1.id
    inner join base_category3 c3 on c3.category2_id = c2.id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    4.2.2.2 创建mapper
    Mapper
    @Mapper
    public interface BaseCategoryViewMapper extends BaseMapper<BaseCategoryView> {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    4.2.2.3 编写接口与实现类

    ManageService

    接口

    /**
     * 通过三级分类id查询分类信息
      * @param category3Id
     * @return
     */
    BaseCategoryView getCategoryViewByCategory3Id(Long category3Id);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    接口实现

    @Override
    public BaseCategoryView getCategoryViewByCategory3Id(Long category3Id) {
        return baseCategoryViewMapper.selectById(category3Id);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    4.2.2.4 编写控制器

    ProductApiController

    ProductApiController
    /**
     * 通过三级分类id查询分类信息
     * @param category3Id
     * @return
     */
    @GetMapping("inner/getCategoryView/{category3Id}")
    public BaseCategoryView getCategoryView(@PathVariable("category3Id")Long category3Id){
        return manageService.getCategoryViewByCategory3Id(category3Id);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.2.3 获取价格信息

    4.2.3.1 编写接口与实现类
    /**
     * 获取sku价格
     * @param skuId
     * @return
     */
    BigDecimal getSkuPrice(Long skuId);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    /**
     * 获取sku价格
     * @param skuId
     * @return
     */
    @Override
    public BigDecimal getSkuPrice(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if(null != skuInfo) {
            return skuInfo.getPrice();
        }
        return new BigDecimal("0");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    4.2.3.2 编写控制器
    /**
     * 获取sku最新价格
     * @param skuId
     * @return
     */
    @GetMapping("inner/getSkuPrice/{skuId}")
    public BigDecimal getSkuPrice(@PathVariable Long skuId){
        return manageService.getSkuPrice(skuId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.2.4 获取销售信息

    在这里插入图片描述

    思路:
    1、查出该商品的spu的所有销售属性和属性值
    2、标识出本商品对应的销售属性 
    3、点击其他销售属性值的组合,跳转到另外的sku页面
    
    • 1
    • 2
    • 3
    • 4
    4.2.4.1 查询出sku对应spu的销售属性

    第1、2条通过此sql实现

    SELECT sa.id ,sa.spu_id, sa.sale_attr_name,sa.base_sale_attr_id,
       sv.id sale_attr_value_id,
       sv.sale_attr_value_name,
       skv.sku_id,
       IF(skv.sku_id IS NULL,0,1)  is_checked
       FROM spu_sale_attr sa
       INNER JOIN spu_sale_attr_value  sv ON  sa.spu_id=sv.spu_id AND sa.base_sale_attr_id=sv.base_sale_attr_id
       LEFT JOIN sku_sale_attr_value skv ON skv.sale_attr_value_id= sv.id AND skv.sku_id=#{skuId}
       WHERE  sa.spu_id=#{spuId}
       ORDER BY sv.base_sale_attr_id,sv.id
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    此sql列出所有该spu的销售属性和属性值,并关联某skuid如果能关联上is_check设为1,否则设为0。

    在对应的实体类中【SpuSaleAttrValue】添加属性字段

    @TableField(exist = false)
    String isChecked;
    
    • 1
    • 2
    MyBatisPlus有个不起眼的字段@TableField,一般不是必须的。但是他有一个属性exist,是表示这个字段在数据库中是否存在(是否实体字段),与JPA的@Transient是类似的。
    于是乎,加个@TableField(exist = false)搞定
    
    @TableField(exist = false):表示该属性不为数据库表字段,但又是必须使用的。
    @TableField(exist = true):表示该属性为数据库表字段。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    4.2.4.2 在SpuSaleAttrMapper 接口中添加的方法

    接口 :SpuSaleAttrMapper

    // 根据spuId,skuId 查询销售属性集合
    List<SpuSaleAttr> selectSpuSaleAttrListCheckBySku(@Param("skuId") Long skuId, @Param("spuId")Long spuId);
    
    • 1
    • 2
    <select id="selectSpuSaleAttrListCheckBySku" resultMap="spuSaleAttrMap">
         SELECT sa.id ,sa.spu_id, sa.sale_attr_name,sa.base_sale_attr_id,
            sv.id sale_attr_value_id,
            sv.sale_attr_value_name,
            skv.sku_id,
            IF(skv.sku_id IS NULL,0,1)  is_checked
            FROM spu_sale_attr sa
            INNER JOIN spu_sale_attr_value  sv ON  sa.spu_id=sv.spu_id AND sa.base_sale_attr_id=sv.base_sale_attr_id
            LEFT JOIN sku_sale_attr_value skv ON skv.sale_attr_value_id= sv.id AND skv.sku_id=#{skuId}
            WHERE  sa.spu_id=#{spuId}
            ORDER BY sv.base_sale_attr_id,sv.id
    </select>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    4.2.4.3 编写接口与实现类

    接口

    /**
     * 根据spuId,skuId 查询销售属性集合
     * @param skuId
     * @param spuId
     * @return
     */
    List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long skuId, Long spuId);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    实现类

    @Override
    public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long skuId, Long spuId) {
        return spuSaleAttrMapper.selectSpuSaleAttrListCheckBySku(skuId, spuId);
    }
    
    • 1
    • 2
    • 3
    • 4
    4.2.4.4 编写控制器
    ProductApiController
    
    /**
     * 根据spuId,skuId 查询销售属性集合
     * @param skuId
     * @param spuId
     * @return
     */
    @GetMapping("inner/getSpuSaleAttrListCheckBySku/{skuId}/{spuId}")
    public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(@PathVariable("skuId") Long skuId,@PathVariable("spuId") Long spuId){
        return manageService.getSpuSaleAttrListCheckBySku(skuId, spuId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.2.5 实现商品切换

    实现思路:

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    1 、从页面中获得得所有选中的销售属性进行组合比如:
    “属性值1|属性值2” 用这个字符串匹配一个对照表,来获得skuId。并进行跳转,或者告知无货。
    2、后台要生成一个“属性值1|属性值2:skuId”的一个json串以提供页面进行匹配。如 
    3、需要从后台数据库查询出该spu下的所有skuId和属性值关联关系。然后加工成如上的Json串,用该json串,跟前台匹配。
    实现:
    使用sql 语句来解决:
    GROUP_CONCAT:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator '分隔符'] )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    4.2.5.1在SkuSaleAttrValueMapper中添加接口

    SkuSaleAttrValueMapper

    // 根据spuId 查询map 集合数据
    List<Map> selectSaleAttrValuesBySpu(Long spuId);
    
    • 1
    • 2

    SkuSaleAttrValueMapper.xml

    
    <resultMap id="spuValueIdsMap" type="java.util.Map" autoMapping="true">
    
    resultMap>
    <select id="selectSaleAttrValuesBySpu" resultMap="spuValueIdsMap">
      SELECT sku_id  , GROUP_CONCAT(sale_attr_value_id  ORDER BY sp.base_sale_attr_id ASC SEPARATOR '|') value_ids
         FROM  `sku_sale_attr_value` sv
         INNER JOIN `spu_sale_attr_value` sp on sp.id = sv.sale_attr_value_id
         WHERE sv.spu_id=#{spuId}
         GROUP BY sku_id
    select>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    4.2.5.2 编写接口与实现类

    ManageService

    接口

    /**
     * 根据spuId 查询map 集合属性
     * @param spuId
     * @return
     */
    Map getSkuValueIdsMap(Long spuId);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    实现类

    @Override
    public Map getSkuValueIdsMap(Long spuId) {
        Map<Object, Object> map = new HashMap<>();
        // key = 125|123 ,value = 37
        List<Map> mapList = skuSaleAttrValueMapper.selectSaleAttrValuesBySpu(spuId);
        if (mapList != null && mapList.size() > 0) {
            // 循环遍历
            for (Map skuMap : mapList) {
                // key = 125|123 ,value = 37
                map.put(skuMap.get("value_ids"), skuMap.get("sku_id"));
            }
        }
        return map;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    4.2.5.3 编写控制器

    ProductApiController

    /**
     * 根据spuId 查询map 集合属性
     * @param spuId
     * @return
     */
    @GetMapping("inner/getSkuValueIdsMap/{spuId}")
    public Map getSkuValueIdsMap(@PathVariable("spuId") Long spuId){
        return manageService.getSkuValueIdsMap(spuId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.2.6 获取海报信息

    4.2.6.1 编写接口与实现类

    接口

    /**
     * 根据spuid获取商品海报
     * @param spuId
     * @return
     */
    List<SpuPoster> findSpuPosterBySpuId(Long spuId);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    实现类

    @Override
    public List<SpuPoster> findSpuPosterBySpuId(Long spuId) {
        QueryWrapper<SpuPoster> spuInfoQueryWrapper = new QueryWrapper<>();
        spuInfoQueryWrapper.eq("spu_id",spuId);
        List<SpuPoster> spuPosterList = spuPosterMapper.selectList(spuInfoQueryWrapper);
        return spuPosterList;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    4.2.6.2 编写控制器
    //  根据spuId 获取海报数据
    @GetMapping("inner/findSpuPosterBySpuId/{spuId}")
    public List<SpuPoster> findSpuPosterBySpuId(@PathVariable Long spuId){
        return manageService.findSpuPosterBySpuId(spuId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.2.7 Sku对应的平台属性

    在这里插入图片描述

    4.2.7.1 编写接口与实现类

    显示在商品详情规格处

    ManageService

    /**
     * 通过skuId 集合来查询数据
     * @param skuId
     * @return
     */
    List<BaseAttrInfo> getAttrList(Long skuId);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    实现类

    @Override
    public List<BaseAttrInfo> getAttrList(Long skuId) {
    
        return baseAttrInfoMapper.selectBaseAttrInfoListBySkuId(skuId);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    BaseAttrInfoMapper 添加方法

       /**
         *
         * @param skuId
         */
        List<BaseAttrInfo> selectBaseAttrInfoListBySkuId(@Param("skuId")Long skuId);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    BaseAttrInfoMapper.xml添加

    <select id="selectBaseAttrInfoListBySkuId" resultMap="baseAttrInfoMap">
        SELECT
        bai.id,
        bai.attr_name,
        bai.category_id,
        bai.category_level,
        bav.id attr_value_id,
        bav.value_name,
        bav.attr_id
        FROM
        base_attr_info bai
        INNER JOIN base_attr_value bav ON bai.id = bav.attr_id
        INNER JOIN sku_attr_value sav ON sav.value_id = bav.id
        WHERE
        sav.sku_id = #{skuId}
    select>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    4.2.7.2 编写控制器

    ProductApiController

    /**
     * 通过skuId 集合来查询数据
     * @param skuId
     * @return
     */
    @GetMapping("inner/getAttrList/{skuId}")
    public List<BaseAttrInfo> getAttrList(@PathVariable("skuId") Long skuId){
        return manageService.getAttrList(skuId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    说明:目前我们在service-product里面把数据模型已经封装好了,接下封装feign client api接口,提供给service-item微服务调用汇总数据模型
    
    • 1

    4.3 搭建service-client父模块

    搭建方式如:common父模块

    4.3.2 修改配置

    修改pom.xml文件

    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
    
        <modules>
           <module>service-product-clientmodule>
           <module>service-item-clientmodule>
        modules>
    
        <parent>
            <groupId>com.atguigu.gmallgroupId>
            <artifactId>gmall-parentartifactId>
            <version>1.0version>
        parent>
    
        <artifactId>service-clientartifactId>
        <packaging>pompackaging>
        <version>1.0version>
    
        <dependencies>
            <dependency>
                <groupId>com.atguigu.gmallgroupId>
                <artifactId>common-utilartifactId>
                <version>1.0version>
            dependency>
    
            <dependency>
                <groupId>com.atguigu.gmallgroupId>
                <artifactId>modelartifactId>
                <version>1.0version>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
                <scope>provided scope>
            dependency>
        dependencies>
    
    project>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    4.4 搭建service-product-client

    4.4.1 构建模块

    在service-client 模块下创建

    4.4.2 修改配置

    修改pom.xml加粗样式

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
          <groupId>com.atguigu.gmall</groupId>
          <artifactId>service-client</artifactId>
          <version>1.0</version>
       </parent>
    
       <artifactId>service-product-client</artifactId>
       <version>1.0</version>
    
       <packaging>jar</packaging>
       <name>service-product-client</name>
       <description>service-product-client</description>
    
    </project>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4.4.3 封装service-product-client接口

    package com.atguigu.gmall.product.client;
    
    @FeignClient(value ="service-product", fallback = ProductDegradeFeignClient.class)
    public interface ProductFeignClient {
    
        /**
         * 根据skuId获取sku信息
         *
         * @param skuId
         * @return
         */
        @GetMapping("/api/product/inner/getSkuInfo/{skuId}")
        SkuInfo getSkuInfo(@PathVariable("skuId") Long skuId);
    
    
        /**
         * 通过三级分类id查询分类信息
         * @param category3Id
         * @return
         */
        @GetMapping("/api/product/inner/getCategoryView/{category3Id}")
        BaseCategoryView getCategoryView(@PathVariable("category3Id")Long category3Id);
    
        /**
         * 获取sku最新价格
         *
         * @param skuId
         * @return
         */
        @GetMapping("/api/product/inner/getSkuPrice/{skuId}")
        BigDecimal getSkuPrice(@PathVariable(value = "skuId") Long skuId);
    
        /**
         * 根据spuId,skuId 查询销售属性集合
         *
         * @param skuId
         * @param spuId
         * @return
         */
        @GetMapping("/api/product/inner/getSpuSaleAttrListCheckBySku/{skuId}/{spuId}")
        List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(@PathVariable("skuId") Long skuId, @PathVariable("spuId") Long spuId);
    
        /**
         * 根据spuId 查询map 集合属性
         * @param spuId
         * @return
         */
        @GetMapping("/api/product/inner/getSkuValueIdsMap/{spuId}")
        Map getSkuValueIdsMap(@PathVariable("spuId") Long spuId);
    
       //  根据spuId 获取海报数据
       @GetMapping("/api/product/inner/findSpuPosterBySpuId/{spuId}")
       List<SpuPoster> getSpuPosterBySpuId(@PathVariable Long spuId);
        /**
         * 通过skuId 集合来查询数据
         * @param skuId
         * @return
         */
        @GetMapping("/api/product/inner/getAttrList/{skuId}")
        List<BaseAttrInfo> getAttrList(@PathVariable("skuId") Long skuId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    @Component
    public class ProductDegradeFeignClient implements ProductFeignClient {
    
        @Override
        public SkuInfo getSkuInfo(Long skuId) {
            return null;
        }
    
        @Override
        public BaseCategoryView getCategoryView(Long category3Id) {
            return null;
        }
    
        @Override
        public BigDecimal getSkuPrice(Long skuId) {
            return null;
        }
    
        @Override
        public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long skuId, Long spuId) {
            return null;
        }
    
    
        @Override
        public Map getSkuValueIdsMap(Long spuId) {
            return null;
        }
        @Override
        public List<SpuPoster> getSpuPosterBySpuId(Long spuId) {
            return null;
        }
        @Override
        public List<BaseAttrInfo> getAttrList(Long skuId) {
            return null;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    说明:接下来service-item引用service-product-client模块,就可以调用相应接口

    在service-item pom.xml引用依赖:

    <dependency>
       <groupId>com.atguigu.gmallgroupId>
       <artifactId>service-product-clientartifactId>
       <version>1.0version>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.5 service-item模块汇总数据

    @Service
    public class ItemServiceImpl implements ItemService {
    
        //  远程调用service-product-client
        @Autowired
        private ProductFeignClient productFeignClient;
    
        @Override
        public Map<String, Object> getItemBySkuId(Long skuId) {
            //  声明对象
            Map<String, Object> result = new HashMap<>();
    
            //  获取到的数据是skuInfo + skuImageList
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
    
            //  判断skuInfo 不为空
            if (skuInfo!=null){
                //  获取分类数据
                BaseCategoryView categoryView = productFeignClient.getCategoryView(skuInfo.getCategory3Id());
                result.put("categoryView",categoryView);
                //  获取销售属性+销售属性值
                List<SpuSaleAttr> spuSaleAttrListCheckBySku = productFeignClient.getSpuSaleAttrListCheckBySku(skuId, skuInfo.getSpuId());
                result.put("spuSaleAttrList",spuSaleAttrListCheckBySku);
                //  查询销售属性值Id 与skuId 组合的map
                Map skuValueIdsMap = productFeignClient.getSkuValueIdsMap(skuInfo.getSpuId());
                //  将这个map 转换为页面需要的Json 对象
                String valueJson = JSON.toJSONString(skuValueIdsMap);
                result.put("valuesSkuJson",valueJson);
    
            }
            //  获取价格
            BigDecimal skuPrice = productFeignClient.getSkuPrice(skuId);
            //  map 中 key 对应的谁? Thymeleaf 获取数据的时候 ${skuInfo.skuName}
            result.put("skuInfo",skuInfo);
            result.put("price",skuPrice);
            //  返回map 集合 Thymeleaf 渲染:能用map 存储数据!
            //  spu海报数据
            List<SpuPoster> spuPosterList =                         productFeignClient.findSpuPosterBySpuId(skuInfo.getSpuId());
            result.put("spuPosterList", spuPosterList);
            List<BaseAttrInfo> attrList = productFeignClient.getAttrList(skuId);
            //  使用拉姆达表示
            List<Map<String, String>> skuAttrList = attrList.stream().map((baseAttrInfo) -> {
                Map<String, String> attrMap = new HashMap<>();
                attrMap.put("attrName", baseAttrInfo.getAttrName());
                attrMap.put("attrValue",         baseAttrInfo.getAttrValueList().get(0).getValueName());
                return attrMap;
            }).collect(Collectors.toList());
            result.put("skuAttrList", skuAttrList);
    
            return result;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    4.6 商品详情页面渲染

    4.6.1 搭建service-item-client模块

    在service-client 目录下创建。

    搭建方式同service-product-client

    接口类

    package com.atguigu.gmall.item.client
    
    @FeignClient(value = "service-item", fallback = ItemDegradeFeignClient.class)
    public interface ItemFeignClient {
    
        /**
         * @param skuId
         * @return
         */
        @GetMapping("/api/item/{skuId}")
        Result getItem(@PathVariable("skuId") Long skuId);
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    @Component
    public class ItemDegradeFeignClient implements ItemFeignClient {
    
    
        @Override
        public Result getItem(Long skuId) {
            return Result.fail();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4.6.2 搭建web-util模块

    4.6.2.1 搭建web-util

    搭建方式如service-util

    4.6.2.2 修改配置pom.xml
    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>commonartifactId>
            <groupId>com.atguigu.gmallgroupId>
            <version>1.0version>
        parent>
        <modelVersion>4.0.0modelVersion>
    
        <artifactId>web-utilartifactId>
    
        <dependencies>
            <dependency>
                <groupId>com.atguigu.gmallgroupId>
                <artifactId>common-utilartifactId>
                <version>1.0version>
            dependency>
    
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
                <scope>providedscope>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
                <scope>provided scope>
            dependency>
        dependencies>
    
    project>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    导入工具类:

    4.6.3 构建web父模块

    构建方式如:common父模块

    修改配置pom.xml

    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modules>
            <module>web-allmodule>
        modules>
    
        <parent>
            <groupId>com.atguigu.gmallgroupId>
            <artifactId>gmall-parentartifactId>
            <version>1.0version>
        parent>
    
        <artifactId>webartifactId>
        <packaging>pompackaging>
        <version>1.0version>
    
        <dependencies>
            <dependency>
                <groupId>com.atguigu.gmallgroupId>
                <artifactId>web-utilartifactId>
                <version>1.0version>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-thymeleafartifactId>
            dependency>
    
            
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
            dependency>
    
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
            dependency>
    
    
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
            dependency>
    
            
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
            dependency>
        dependencies>
    
    project>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    4.6.4 构建web-all模块

    4.6.4.1 搭建web-all模块

    搭建方式在web模块下创建

    4.6.4.2 修改pom.xml文件
    <modelVersion>4.0.0modelVersion>
    <parent>
       <groupId>com.atguigu.gmallgroupId>
       <artifactId>webartifactId>
       <version>1.0version>
    parent>
    
    <artifactId>web-allartifactId>
    <version>1.0version>
    
    <packaging>jarpackaging>
    <name>web-all name>
    <description>web-all description>
    
    <dependencies>
       <dependency>
          <groupId>com.atguigu.gmallgroupId>
          <artifactId>service-item-clientartifactId>
          <version>1.0version>
       dependency>
    dependencies>
    
    
    <build>
       <finalName>web-allfinalName>
       <plugins>
          <plugin>
             <groupId>org.springframework.bootgroupId>
             <artifactId>spring-boot-maven-pluginartifactId>
          plugin>
       plugins>
    build>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    4.6.4.3 添加配置文件

    bootstrap.properties

    spring.application.name=web-all
    spring.profiles.active=dev
    spring.cloud.nacos.discovery.server-addr=192.168.200.129:8848
    spring.cloud.nacos.config.server-addr=192.168.200.129:8848
    spring.cloud.nacos.config.prefix=${spring.application.name}
    spring.cloud.nacos.config.file-extension=yaml
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    启动类;

    
    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源自动配置
    @ComponentScan({"com.atguigu.gmall"})
    @EnableDiscoveryClient
    @EnableFeignClients(basePackages= {"com.atguigu.gmall"})
    public class WebAllApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(WebAllApplication.class, args);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    4.6.4.4 将web-all 模块添加到网关

    1,由于我们的微服务接口都是通过网关暴露服务,所以需要配置网关

    server-gateway网关添加配置:
    routes:
    - id: service-product
      uri: lb://service-product
      predicates:
      - Path=/*/product/** # 路径匹配
    - id: service-item
      uri: lb://service-item
      predicates:
      - Path=/*/item/**
    #==================web前端==========================
    - id: web-item
      uri: lb://web-all
      predicates:
      - Host=item.gmall.com
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    4.6.4.5 导入静态资源

    在web-all 工 将这两个文件夹放入到resouces 文件夹中。

    导入之后,可能发送异常警告

    在这里插入图片描述

    解决方案:

    在这里插入图片描述

    4.6.5 编写web-all中的控制器

    4.6.5.1 在web-all调用接口
    Package com.atguigu.gmall.all.controller
    @Controller
    public class ItemController {
    
        @Autowired
        private ItemFeignClient itemFeignClient;
    
        /**
         * sku详情页面
              * @param skuId
         * @param model
         * @return
         */
        @RequestMapping("{skuId}.html")
        public String getItem(@PathVariable Long skuId, Model model){
            // 通过skuId 查询skuInfo
            Result<Map> result = itemFeignClient.getItem(skuId);
            model.addAllAttributes(result.getData());
            return "item/index";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    JavaScript基础05——字面量、变量介绍及变量基本使用
    Spring Securtity (九)会话固定攻击和跨站请求伪造
    人血清白蛋白功能化纳米四氧化三铁Fe3O4
    VBA_MF系列技术资料1-207
    数组题目总结 ---- 田忌赛马
    最小生成树
    经典算法学习之------快速排序
    Docker高级——2 DockerFile解析和3 Docker微服务实战
    TYUT太原理工大学2022需求工程考试简答题
    java计算机毕业设计教师职称评定系统源码+mysql数据库+系统+lw文档+部署
  • 原文地址:https://blog.csdn.net/guan1843036360/article/details/127461907