畅购电商项目-05-搜索模块-2021-06-23

6.搜索模块

6.1构建列表页

  • 步骤一:创建 ~/pages/list/_cid.vue 页面

在这里插入图片描述

  • 步骤二:复制静态list.html页面到 list/_cid.vue中,并修改js和css引用方式
  • 1)修改页面,完善标签
    在这里插入图片描述
  • 2)替换图片路径
    在这里插入图片描述
<template>
  <div>
    <!-- 顶部导航 start -->

    <!-- 
		省略 html原有内容 
	-->

    <!-- 底部版权 end -->

  </div>
</template>

<script>
export default {
  head: {
    title: '列表页面',
    link: [
      {rel:'stylesheet',href: '/style/list.css'},
      {rel:'stylesheet',href: '/style/common.css'},
      {rel:'stylesheet',href: '/style/bottomnav.css'},
    ],
    script: [
      { type: 'text/javascript', src: '/js/header.js' },
      { type: 'text/javascript', src: '/js/list.js' },
    ]
  },
}
</script>

<style>

</style>
  • 步骤三:添加已有组件
<template>
  <div>
    <!-- 顶部导航 start -->
    <TopNav></TopNav>
    <!-- 顶部导航 end -->

    <div style="clear:both;"></div>

    <!-- 头部 start -->
    <HeaderSearch></HeaderSearch>
    <!-- 头部 end-->

    <div style="clear:both;"></div>

    <!-- 列表主体 start -->
    <!-- 省略 html原有内容 -->
    <!-- 列表主体 end-->

    <div style="clear:both;"></div>
    <!-- 底部导航 start -->
    <BottomNav></BottomNav>
    <!-- 底部导航 end -->

    <div style="clear:both;"></div>
    <!-- 底部版权 start -->
    <Footer></Footer>
    <!-- 底部版权 end -->

  </div>
</template>

<script>
import TopNav from '../../components/TopNav'
import HeaderSearch from '../../components/HeaderSearch'
import BottomNav from '../../components/BottomNav'
import Footer from '../../components/Footer'

export default {
  head: {
    title: '列表页面',
    link: [
      {rel:'stylesheet',href: '/style/list.css'},
      {rel:'stylesheet',href: '/style/common.css'},
      {rel:'stylesheet',href: '/style/bottomnav.css'},
    ],
    script: [
      { type: 'text/javascript', src: '/js/header.js' },
      { type: 'text/javascript', src: '/js/list.js' },
    ]
  },
  components: {
    TopNav,
    HeaderSearch,
    BottomNav,
    Footer
  },
}
</script>

<style>

</style>

6.2优化组件HeaderSearch组件

  • 非首页“HeaderSearch”组件,不能隐藏分类
    在这里插入图片描述
  • 步骤一:修改HeaderSearch组件,添加props
export default {
  props: {
    isFirst: {    //是否是首页
      type: Boolean,
      default: true
    }
  }
}
  • 步骤二:如果不在首页时,在指定的3处添加样式
    在这里插入图片描述
  • 步骤三:修改 ~/pages/list/_id.vue ,将HeaderSearch组件的isFirst属性修改成false
    在这里插入图片描述
  • 步骤四:显示分类数据
    在这里插入图片描述
<!-- 头部 start -->
    <HeaderSearch :isFirst="false" :list="categorysList"></HeaderSearch>
    <!-- 头部 end-->
async asyncData( { app } ) {
    // 查询快报 + 查询分类
    let [{data: categoryData}] = await Promise.all([
                    app.$requestServer.findCategorys()
                  ])
    return {
      categorysList : categoryData.data
    }
  }
  • 步骤五:修改logo访问路径
    在这里插入图片描述

6.3指定分类的所有品牌

  • 6.3.1接口
GET http://localhost:10010/web-service/brands/category/76

在这里插入图片描述

6.3.2后端实现:JavaBean

  • 表结构分析:
  • 分类表:tb_category
  • 品牌表:tb_brand
    关系:多对多(不同的分类,拥有不同的品牌)tb_category_bran
package com.czxy.changgou4.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
@TableName("tb_brand")
public class Brand {
    @TableId(type = IdType.AUTO)
    private Integer id;                 //品牌id

    @TableField(value = "brand_name")
    private String brandName;           //品牌名称

    @TableField(value = "logo")
    private String logo;                //品牌图片地址

}

6.3.3后端实现:查询

  • 步骤一:创建BrandMapper接口,根据分类查询所有的品牌
package com.czxy.changgou4.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Brand;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Mapper
public interface BrandMapper extends BaseMapper<Brand> {

    /**
     * 根据分类查询所有的品牌
     * @param categoryId
     * @return
     */
    @Select("select b.* from tb_brand b ,tb_category_brand cb " +
            "  where b.id = cb.brand_id and cb.category_id = #{categoryId}")

    public List<Brand> findAll(@Param("categoryId") Integer categoryId);

}
  • 步骤二:创建BrandService接口
package com.czxy.changgou4.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Brand;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface BrandService extends IService<Brand> {
    /**
     * 根据分类查询所有的品牌
     * @param categoryId
     * @return
     */
    public List<Brand> findAll(Integer categoryId);
}
  • 步骤三:编写BrandService实现类
package com.czxy.changgou4.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.BrandMapper;
import com.czxy.changgou4.pojo.Brand;
import com.czxy.changgou4.service.BrandService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Service
@Transactional
public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements BrandService {


    @Override
    public List<Brand> findAll(Integer categoryId) {
        return baseMapper.findAll(categoryId);
    }
}
  • 步骤四:创建BrandController,符合接口规范
package com.czxy.changgou4.controller;

import com.czxy.changgou4.pojo.Brand;
import com.czxy.changgou4.service.BrandService;
import com.czxy.changgou4.vo.BaseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@RestController
@RequestMapping("/brands")
public class BrandController {

    @Resource
    private BrandService brandService;

    /**
     * //GET /brands/category/76
     * @param categoryId
     * @return
     */
    @GetMapping("/category/{categoryId}")
    public BaseResult findAll(@PathVariable("categoryId") Integer categoryId){
        //1 查询
        List<Brand> list = this.brandService.findAll( categoryId );
        //2 封装
        return BaseResult.ok("查询成功", list );
    }

}

6.3.4前端实现

  • 步骤一:修改apiclient.js,编写ajax
    在这里插入图片描述
//指定分类的品牌
  findBrand : (categoryId) => {
    return axios.get('/web-service/brands/category/' + categoryId)
  }
  • 步骤二:修改 ~/pages/list/_cid 页面,页面加载成功后,获得分类id
data() {
    return {
      searchMap: {      //搜索条件对象
        catId: ''          //分类id
      }
    }
  },
  async mounted() {
    //设置id
    this.searchMap.catId = this.$route.params.cid

  },
  • 步骤三:修改 ~/pages/list/_cid.vue 页面,查询品牌
data() {
    return {
      searchMap: {      //搜索条件对象
        catId: ''          //分类id
      },
      brandList : [],   //所有品牌

    }
  },
  methods: {
    async findAllBrandFn() {
      let { data : brandData } = await this.$request.findBrand( this.searchMap.catId )
      this.brandList = brandData.data
    }
  },
  async mounted() {

    //设置id
    this.searchMap.catId = this.$route.params.cid
    // 查询所有的品牌
    this.findAllBrandFn()

  },
  • 步骤四:修改 ~/pages/list/_id 页面,显示分类数据
    在这里插入图片描述
<dl>
  <dt>品牌:</dt>
  <dd :class="{'cur' : searchMap.brandId == '' }"><a href="" @click.prevent="brandSearch('')">不限</a></dd>
  <dd :class="{'cur' : searchMap.brandId == bl.id}" v-for="(bl,bli) in brandList" :key="bli">
       <a :href="bl.link" @click.prevent="brandSearch(bl.id)">{{bl.brandName}}</a>
   </dd>
</dl>
  • 步骤五:修改 ~/pages/list/_id 页面,回显选中数据
    在这里插入图片描述
methods: {
    brandSearch (bid){
      //记录品牌id
      this.searchMap.brandId = bid;
      //查询
      this.searchList();
    },
    searchList () {
      console.info(this.searchMap)
    }
  },

6.4指定分类的所有规格

  • 6.4.1接口
GET http://localhost:10010/web-service/specifications/category/76

在这里插入图片描述

6.4.2后端实现:JavaBean

  • 表结构分析:
  • 规格表:tb_specification
  • 规格选项表:tb_specification_option
  • 关系:一对多(一个规格,拥有多个规格选项)
    在这里插入图片描述
  • 规格选项
package com.czxy.changgou4.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@TableName("tb_specification_option")
@Data
public class SpecificationOption {
    /*
    CREATE TABLE `tb_specification_option` (
           `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
           `spec_id` int(10) unsigned NOT NULL COMMENT '规格ID',
           `option_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '选项名称',
           PRIMARY KEY (`id`),
           KEY `specification_options_spec_id_index` (`spec_id`)
         )
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    @TableField(value="spec_id")
    @JsonProperty("spec_id")
    private Integer specId;                //外键,规格ID

    private Specification specification; //外键对应对象

    @TableField(value="option_name")
    @JsonProperty("option_name")
    private String optionName;             //选项名称


}
  • 规格
package com.czxy.changgou4.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@TableName("tb_specification")
@Data
public class Specification {
    /*
    CREATE TABLE `tb_specification` (
            `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
            `spec_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '规格名称',
            `category_id` int(10) unsigned NOT NULL COMMENT '分类ID',
            PRIMARY KEY (`id`)
          )
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    @TableField(value = "spec_name")
    @JsonProperty("spec_name")
    private String specName;                    //规格名称

    @TableField(value = "category_id")
    private Integer categoryId;                     //分类外键
    private Category category;                      //分类外键对应对象


    private List<SpecificationOption> options;      //一个规格,具有多个规格选项

}

6.4.3后端实现:查询

  • 查询规格的同时,查询对应的规格选项
  • 步骤一:创建 SpecificationOptionMapper,用于查询指定“规格”的所有“规格选项”
package com.czxy.changgou4.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.SpecificationOption;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Mapper
public interface SpecificationOptionMapper extends BaseMapper<SpecificationOption> {

    /**
     * 查询指定规格的所有规格选项
     * @param spceId
     * @return
     */
    @Select("select * from tb_specification_option where spec_id = #{specId}")
    @Results({
            @Result(property = "id",column = "id"),
            @Result(property = "specId",column = "spec_id"),
            @Result(property = "optionName",column = "option_name"),
    })
    public List<SpecificationOption> findSpecOptionBySpecId(@Param("specId") Integer spceId);

}
  • 步骤二:创建SpecificationMapper,查询指定分类的所有规格,含规格选项信息
package com.czxy.changgou4.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Specification;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Mapper
public interface SpecificationMapper extends BaseMapper<Specification> {
    /**
     * 查询指定分类的所有规格
     * @param categoryId
     * @return
     */
    @Select("select * from tb_specification where category_id = #{categoryId}")
    @Results({
            @Result(property = "id", column = "id"),
            @Result(property = "specName", column = "spec_name"),
            @Result(property = "categoryId", column = "category_id"),
            @Result(property = "options", many=@Many(select="com.czxy.changgou4.mapper.SpecificationOptionMapper.findSpecOptionBySpecId"), column = "id"),
    })
    public List<Specification> findSpecificationByCategoryId(@Param("categoryId") Integer categoryId);

}
  • 步骤三:创建SpecificationService接口
package com.czxy.changgou4.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Specification;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface SpecificationService extends IService<Specification> {
    /**
     * 查询指定分类的所有规格
     * @param categoryId
     * @return
     */
    public List<Specification> findSpecificationByCategoryId(Integer categoryId);
}
  • 步骤四:创建SpecificationService实现类
package com.czxy.changgou4.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.SpecificationMapper;
import com.czxy.changgou4.pojo.Specification;
import com.czxy.changgou4.service.SpecificationService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Service
@Transactional
public class SpecificationServiceImpl extends ServiceImpl<SpecificationMapper, Specification> implements SpecificationService {
    @Override
    public List<Specification> findSpecificationByCategoryId(Integer categoryId) {
        return baseMapper.findSpecificationByCategoryId(categoryId);
    }
}
  • 步骤五:创建 SpecificationController
package com.czxy.changgou4.controller;

import com.czxy.changgou4.pojo.Specification;
import com.czxy.changgou4.service.SpecificationService;
import com.czxy.changgou4.vo.BaseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@RestController
@RequestMapping("/specifications")
public class SpecificationController {
    @Resource
    private SpecificationService specificationService;

    /**
     * GET /specifications/category/:catid
     * @param categoryId
     * @return
     */
    @GetMapping("/category/{catId}")
    public BaseResult findSpecificationByCategoryId(@PathVariable("catId") Integer categoryId){
        //1 查询
        List<Specification> list = this.specificationService.findSpecificationByCategoryId(categoryId);
        //2 封装
        return BaseResult.ok("查询成功", list);
    }

}

6.4.4前端实现

  • 步骤一:修改 api.js ,查询规格
    在这里插入图片描述
//指定分类的规格
  findSpec : (categoryId) => {
    return axios.get('/web-service/specifications/category/' + categoryId)
  },
  • 步骤二:修改 pages/list/_id ,页面加载成功,查询规格
data() {
    return {
      searchMap: {      //搜索条件对象
        catId: '',      //分类id
        brandId: '',    // 品牌id
      },
      brandList : [],   //所有品牌
      specList : [],    //所有规格

    }
  },
  methods: {
    async findAllBrandFn() {
      let { data : brandData } = await this.$request.findBrand( this.searchMap.catId )
      this.brandList = brandData.data
    },
    async findAllSpecFn() {
      let { data : specData } = await this.$request.findSpec( this.searchMap.catId )
      this.specList = specData.data
    },
    brandSearch(bid) {
      //记录品牌id
      this.searchMap.brandId = bid;

      //查询
      this.searchList();
    },
    searchList () {
      console.info(this.searchMap)
    }

  },
  async mounted() {

    //设置id
    this.searchMap.catId = this.$route.params.cid
    // 查询所有的品牌
    this.findAllBrandFn()
    // 查询所有的规格
    this.findAllSpecFn()

  },
  • 步骤三:显示数据
    在这里插入图片描述
<!--显示规格数据-->
            <dl v-for="(sl,sli) in specList" :key="sli">
              <dt>{{sl.spec_name}}</dt>
              <dd :class="{'cur': sl.selectId == ''}"><a href="" @click.prevent="specSearch(sl ,'' , )">不限</a></dd>
              <dd :class="{'cur' : sl.selectId == op.id }" v-for="(op,opi) in sl.options" :key="opi">
                <a href="" @click.prevent="specSearch(sl ,op , )">{{op.option_name}}</a>
              </dd>
            </dl>
  • 步骤四:选中规格,整体内容回显
 specSearch (spec , option ) {

      //记录选中的id
      this.$set(spec,'selectId', option ? option.id : '' )

    }

6.5前置技术:ElasticSearch

参考《elasticsearch入门.doc》

6.6电商概念:SKU和SPU
  • SPU = Standard Product Unit (标准产品单位)

  • SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。
    通俗点讲,属性值、特性相同的商品就可以称为一个SPU。

  • 例如:
    iphone X就是一个SPU,与颜色、款式、套餐都无关。

  • SKU=stock keeping unit(库存量单位)

  • SKU即库存进出计量的单位, 可以是以件、盒、托盘等为单位。
    SKU是物理上不可分割的最小存货单元。

  • 例如:
    iPhone X 128G 黑色,就是一个SKU

  • 总结
    SPU:可以理解为一类商品的总称(一组产品特性的集合)
    SKU:可以称之为最小库存单位,也就是所能唯一确定一件商品的唯一标识。

6.7流程分析

  • sku查询功能:从数据库查询sku相关的所有信息
  • 数据同步:将数据库中的数据,同步到es中。()
  • 数据库查询搜索慢、es查询速度快
  • 同步时机:1. 定时器(理论)、2. 测试程序(实施)
  • 搜索服务:从elasticsearch中搜索数据,默认情况下es中没有数据,通过“数据同步”操作后,es有数据
    在这里插入图片描述

6.8表结构分析

  • 商品相关表总览
    在这里插入图片描述
  • 表间关系
    在这里插入图片描述

6.9查询所有SKU

  • 接口
GET http://localhost:10010/web-service/sku/esData

在这里插入图片描述

6.9.2后端实现:JavaBean

在这里插入图片描述

  • 数据库相关JavaBean
  • Spu类似分类
  • Sku 商品详情
  • SkuComment sku的评论
  • ES相关JavaBean
  • ESData 准备存放到es中的数据,是以上三种数据的组合数据。

SPU

package com.czxy.changgou4.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.util.Date;

/**
 * Created by liangtong.
 */
@TableName("tb_spu")
@Data
public class Spu {

    @TableId(type = IdType.AUTO)
    private Integer id;

    //spu名字
    @TableField(value="spu_name")
    private String spuName;
    //spu副名称
    @TableField(value="spu_subname")
    private String spuSubname;
    //商品logo
    @TableField(value="logo")
    private String logo;
    //分类1Id
    @TableField(value="cat1_id")
    private Integer cat1Id;
    //分类2ID
    @TableField(value="cat2_id")
    private Integer cat2Id;
    //分类3Id
    @TableField(value="cat3_id")
    private Integer cat3Id;

    @TableField(value="brand_id")
    private Integer brandId;
    @TableField(exist = false)
    private Brand brand;
    //审核时间
    @TableField(value="check_time")
    private String checkTime;
    //审核状态 审核状态,0:未审核,1:已通过,2:未通过
    @TableField(value="check_status")
    private String checkStatus;
    //价格
    @TableField(value="price")
    private String price;
    //是否上架
    @TableField(value="is_on_sale")
    private Integer isOnSale;
    //上架时间
    @TableField(value="on_sale_time")
    private Date onSaleTime;
    //删除时间
    @TableField(value="deleted_at")
    private String deletedAt;

    @TableField(value="weight")
    private String weight;

    //商品描述
    @TableField(value="description")
    private String description;
    //规格与包装
    @TableField(value="packages")
    private String packages;
    //售后保障
    @TableField(value="aftersale")
    private String aftersale;
    //规格列表,json串
    @TableField(value="spec_list")
    private String specList;

    @TableField(value="created_at")
    private String createdAt;
    @TableField(value="updated_at")
    private String updatedAt;


}
  • Sku
package com.czxy.changgou4.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * Created by liangtong.
 */
@TableName("tb_sku")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Sku {

    @TableId(type = IdType.AUTO)
    private Integer id;
    //库存量
    @TableField(value="stock")
    private Integer stock;

    @TableField(value="spu_id")
    private Integer spuId;
    @TableField(exist = false)
    private Spu spu;
    //sku名字
    @TableField(value="sku_name")
    private String skuName;

    @TableField(value="images")
    private String images;
    @TableField(value="price")
    private Double price;

    //1:1|2:6|6:22
    @TableField(value="spec_info_id_list")
    private String specInfoIdList;
    //规格列表码,格式:{"机身颜色":"白色","内存":"3GB","机身存储":"16GB"}
    @TableField(value="spec_info_id_txt")
    private String specInfoIdTxt;


}
  • SkuComment
package com.czxy.changgou4.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;


/**
 * Created by liangtong.
 */
@TableName("tb_sku_comment")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SkuComment {

    @TableId(type = IdType.AUTO)
    private Integer id;
    @TableField(value="created_at")
    private Date createdAt;
    @TableField(value="updated_at")
    private Date updatedAt;

    @TableField(value="user_id")
    private Integer userId;
    @TableField(exist = false)
    private User user;

    @TableField(value="spu_id")
    private Integer spuId;
    @TableField(exist = false)
    private Spu spu;

    @TableField(value="sku_id")
    private Integer skuId;
    @TableField(exist = false)
    private Sku sku;

    @TableField(value="ratio")
    private String ratio;

    @TableField(value="spec_list")
    private String specList;


    @TableField(value="content")
    private String content;
    @TableField(value="star")
    private Integer star;
    @TableField(value="isshow")
    private String isShow;

    @TableField(value="sn")
    private String sn;

}
  • SkuPhoto
package com.czxy.changgou4.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

/**
 * Created by liangtong.
 */
@TableName("tb_sku_photo")
@Data
public class SkuPhoto {

    @TableId(type = IdType.AUTO)
    private Integer id;
    //外键
    @TableField(value="sku_id")
    @JsonProperty("sku_id")
    private Integer skuId;
    @TableField(exist = false)
    private Sku sku;

    @TableField(value="url")
    private String url;

}
  • ESData
package com.czxy.changgou4.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;
import java.util.Map;

/**
 * Created by liangtong.
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ESData {

    private Integer id; // skuId
    private String logo;//图片地址
    private String skuName;//sku名字
    private String all; // 所有需要被搜索的信息,包含标题,分类,甚至品牌
    private Date onSaleTime;//上架时间
    //品牌编号
    private Integer brandId;
    //分类id
    private Integer catId;
    //规格列表
    private Map<String, Object> specs;// 可搜索的规格参数,key是参数名,值是参数值
    private Double price;// 价格
    private String spuName;
    private Integer stock;
    private String description;
    private String packages;//规格与包装
    private String aftersale;//售后保障
    private String midlogo;
    //评价数
    private Integer commentCount;
    // 销量
    private Integer sellerCount;


}

6.9.3后端实现:搭建环境

  • 步骤一:修改父项目的pom.xml,锁定fastjson的依赖
<fastjson.version>1.2.9</fastjson.version>
<!--fastjson-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>${fastjson.version}</version>
</dependency>
  • 步骤二:修改web服务,添加fastjson依赖
<!--json转换-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
</dependency>
  • 步骤三:修改网关,确定 ESData路径
    在这里插入图片描述

6.9.4后端实现:查询

在这里插入图片描述

  • SpuMapper:通过SpuId查询详情,含品牌信息
package com.czxy.changgou4.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Spu;
import org.apache.ibatis.annotations.*;

/**
 * Created by liangtong.
 */
@Mapper
public interface SpuMapper extends BaseMapper<Spu> {

    @Select("select * from tb_spu where id = #{spuId}")
    @Results({
        @Result(property = "spuName" , column = "spu_name"),
        @Result(property = "spuSubname" , column = "spu_subname"),
        @Result(property = "cat1Id" , column = "cat1_id"),
        @Result(property = "cat2Id" , column = "cat2_id"),
        @Result(property = "cat3Id" , column = "cat3_id"),
        @Result(property = "brandId" , column = "brand_id"),
        @Result(property = "checkTime" , column = "check_time"),
        @Result(property = "checkStatus" , column = "check_status"),
        @Result(property = "isOnSale" , column = "is_on_sale"),
        @Result(property = "onSaleTime" , column = "on_sale_time"),
        @Result(property = "deletedAt" , column = "deleted_at"),
        @Result(property = "specList" , column = "spec_list"),
        @Result(property = "onSaleTime" , column = "on_sale_time"),
        @Result(property = "createdAt" , column = "created_at"),
        @Result(property = "updatedAt" , column = "updated_at"),
        @Result(property="brand", column="brand_id",
            one=@One(
                select="com.czxy.changgou4.mapper.BrandMapper.selectById"
            ))
    })
    public Spu findSpuById(@Param("spuId") Integer spuId);

}
  • SkuCommentMapper:查询评论数
package com.czxy.changgou4.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.SkuComment;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * Created by liangtong.
 */
@Mapper
public interface SkuCommentMapper extends BaseMapper<SkuComment> {

    /**
     * 查询评论数
     * @param spu_id
     * @return
     */
    @Select("select count(*) from tb_sku_comment where spu_id = #{spu_id}")
    public Integer findNumBySpuId(@Param("spu_id") Integer spu_id);

    }

  • SkuMapper:查询所有sku,含对应的spu信息
package com.czxy.changgou4.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Sku;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * Created by liangtong.
 */
@Mapper
public interface SkuMapper extends BaseMapper<Sku> {

    @Select("select * from tb_sku")
    @Results(id="skuResult" , value={
            @Result(id=true,column="id",property="id"),
            @Result(column="stock",property="stock"),
            @Result(column="spu_id",property="spuId"),
            @Result(column="sku_name",property="skuName"),
            @Result(column="spec_info_id_list",property="specInfoIdList"),
            @Result(column="spec_info_id_txt",property="specInfoIdTxt"),
            @Result(column="spu_id",property="spu",
                    one=@One(
                            select="com.czxy.changgou4.mapper.SpuMapper.findSpuById"
                    ))
    })
    public List<Sku> findAllSkus();


}SkuPhotoMapper

package com.czxy.changgou4.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.SkuPhoto;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * Created by liangtong.
 */
@Mapper
public interface SkuPhotoMapper extends BaseMapper<SkuPhoto> {


}

在这里插入图片描述

package com.czxy.changgou4.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Sku;
import com.czxy.changgou4.vo.ESData;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface SkuService extends IService<Sku> {

    /**
     *
     * @return
     */
    public List<ESData> findESData();
}


package com.czxy.changgou4.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.SkuCommentMapper;
import com.czxy.changgou4.mapper.SkuMapper;
import com.czxy.changgou4.pojo.Sku;
import com.czxy.changgou4.service.SkuService;
import com.czxy.changgou4.vo.ESData;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Service
@Transactional
public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements SkuService {

    @Resource
    private SkuCommentMapper skuCommentMapper;

    @Override
    public List<ESData> findESData() {
        //1 查询所有详情sku
        List<Sku> skulist = baseMapper.findAllSkus();

        //2 将SKU 转换成 ESData
        List<ESData> esDataList = new ArrayList<>();

        for (Sku sku:skulist){
            ESData esData = new ESData();
            // id
            esData.setId(sku.getId());
            // 图片地址
            esData.setLogo(sku.getSpu().getLogo());
            // 商品名称
            esData.setSkuName(sku.getSkuName());
            // all  “华为xx {"机身颜色":"白色","内存":"3GB","机身存储":"16GB"} 荣耀 ”
            esData.setAll(sku.getSkuName()+"   " + sku.getSpecInfoIdTxt() + "   " +sku.getSpu().getBrand().getBrandName());
            // on_sale_time
            esData.setOnSaleTime(sku.getSpu().getOnSaleTime());
            // brand_id
            esData.setBrandId(sku.getSpu().getBrandId());
            // cat_id
            esData.setCatId(sku.getSpu().getCat3Id());
            //  Map<String, Object> specs;// 可搜索的规格参数,key是参数名,值是参数值
            Map<String,Object> specs = JSON.parseObject(sku.getSpecInfoIdTxt(), Map.class);
//            Map newSpecs = new HashMap();
//            for(String key : specs.keySet()){
//                newSpecs.put("spec" + key , specs.get(key));
//            }

            esData.setSpecs(specs);
            // price 价格
            esData.setPrice(sku.getPrice());
            // spu_name
            esData.setSpuName(sku.getSpu().getSpuName());
            // stock 库存
            esData.setStock(sku.getStock());
            // description
            esData.setDescription(sku.getSpu().getDescription());
            // packages;//规格与包装
            esData.setPackages(sku.getSpu().getPackages());
            // aftersale;//售后保障
            esData.setAftersale(sku.getSpu().getAftersale());
            // midlogo;
            esData.setMidlogo(sku.getSpu().getLogo());
            // comment_count; 评价数
            Integer comment_count = skuCommentMapper.findNumBySpuId(sku.getSpu().getId());
            esData.setCommentCount(comment_count);

            //销售量
            esData.setSellerCount(10);

            esDataList.add(esData);
        }

        return esDataList;

    }

}

在这里插入图片描述

package com.czxy.changgou4.controller;

import com.czxy.changgou4.service.SkuService;
import com.czxy.changgou4.vo.BaseResult;
import com.czxy.changgou4.vo.ESData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@RestController
@RequestMapping("/sku")
public class SkuController {

    @Autowired
    private SkuService skuService;


    @GetMapping("/esData")
    public BaseResult<List<ESData>> findESData(){

        List<ESData> esData = skuService.findESData();
        return BaseResult.ok("查询成功", esData);
    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 2019年黑马项目-畅购商城springcloud微服务实战是一门以实战为主的课程,旨在通过项目实践的方式,帮助学员深入理解和掌握SpringCloud微服务架构以及相关技术的应用。 课程的主要内容包括搭建基础的微服务架构、使用SpringCloud构建服务注册与发现、实现服务间的负载均衡、实现分布式配置中心、服务间的调用与容错处理、使用网关统一接入服务等。通过这些实战练习,学员不仅能够熟悉SpringCloud架构与组件,还能够了解微服务架构下的常见问题与解决方案。 畅购商城项目是一个典型的电商应用,通过实现该项目,学员可以接触到真实的业务场景与需求,并能够将所学知识应用到实际项目中。课程中通过模块化的方式逐步完善商城的功能,包括用户注册登录、商品浏览、购物车管理、订单生成与支付等。通过这些实践,学员除了掌握SpringCloud微服务的开发技术,还能够了解和掌握电商项目的开发流程和注意事项。 该课程的目标是让学员通过实战项目,全面了解和掌握SpringCloud微服务架构的设计与开发,在此基础上能够独立完成具有较高要求的微服务项目。通过参与实战项目的过程,学员还能够提升团队协作能力、解决问题的能力以及项目管理能力。 通过这门课程的学习,学员将会对SpringCloud微服务架构有更深入的理解,并能够将这些知识应用到实际项目中,提高自己在微服务开发领域的竞争力。 ### 回答2: 2019年黑马项目-畅购商城springcloud微服务实战是一个基于springcloud微服务架构的商城项目。该项目的目标是通过运用微服务的理念和技术,构建一个高可用、可扩展的商城系统。 在该项目中,使用了springcloud的多个组件,如Eureka注册中心、Feign负载均衡、Ribbon客户端负载均衡、Hystrix服务降级和容错、Zuul网关等。这些组件共同协作,实现了系统的弹性伸缩和高可用性。 畅购商城的功能包括商品展示、购物车、订单管理、支付、用户管理等。通过将这些功能拆分成独立的微服务,使得系统更加灵活和可维护。同时,使用分布式事务和消息队列来保障数据的一致性和可靠性。 在项目的开发过程中,采用了敏捷开发的方法,以迭代的方式进行开发和测试。通过使用Jenkins进行持续集成和部署,保证了代码的质量和系统的稳定性。 在项目的实战过程中,面临了许多挑战和困难,如微服务之间的通信、服务的负载均衡、服务的容错等。但通过团队的共同努力和不断的学习,最终成功地完成了该项目的开发和部署。 在该项目的实施过程中,不仅学到了springcloud微服务架构的相关知识和技术,还体会到了团队合作和解决问题的能力。该项目的成功实施,不仅为公司带来了商业价值,也提升了团队的技术水平和项目管理能力。 ### 回答3: 2019年黑马项目-畅购商城springcloud微服务实战是一个以Spring Cloud为基础的微服务项目。微服务架构是一种将应用拆分成多个小型服务的架构模式,这些服务可以独立开发、部署、扩展和管理畅购商城项目使用了Spring Cloud的一系列子项目,如Eureka、Ribbon、Feign、Hystrix、Zuul等,来实现各个微服务之间的通信、负载均衡、服务降级与熔断等功能。 在项目中,我们会通过Eureka来实现服务的注册与发现,每个微服务都会向Eureka注册自己的地址,其他微服务可以通过Eureka来发现并调用这些服务。而Ribbon则负责实现客户端的负载均衡,可以轮询、随机、加权等方式分发请求。 Feign是一种声明式的HTTP客户端,它简化了服务间的调用方式。我们只需编写接口,并通过注解来描述需要调用的服务和方法,Feign会自动实现远程调用。 Hystrix是一个容错机制的实现,可以通过断路器来实现服务的降级与熔断,当某个服务出现故障或超时时,Hystrix会快速响应并返回一个可控制的结果,从而保证系统的稳定性。 另外,Zuul作为微服务网关,可以实现请求的统一入口和路由转发,提高系统的安全性和性能。 通过这些Spring Cloud的组件,畅购商城项目可以实现高可用、容错、自动扩展等优质的微服务架构。 总之,2019年黑马项目-畅购商城springcloud微服务实战是一个基于Spring Cloud的微服务项目,通过使用Spring Cloud的各个子项目,可以实现微服务之间的通信、负载均衡、服务降级与熔断等功能,为项目的开发、部署和管理提供了便利。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值