前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >商城项目-实现商品分类查询

商城项目-实现商品分类查询

作者头像
cwl_java
发布2020-02-11 13:44:32
1.8K0
发布2020-02-11 13:44:32
举报
文章被收录于专栏:cwl_Javacwl_Java

5.实现商品分类查询

商城的核心自然是商品,而商品多了以后,肯定要进行分类,并且不同的商品会有不同的品牌信息,其关系如图所示:

在这里插入图片描述
在这里插入图片描述
  • 一个商品分类下有很多商品
  • 一个商品分类下有很多品牌
  • 而一个品牌,可能属于不同的分类
  • 一个品牌下也会有很多商品

因此,我们需要依次去完成:商品分类、品牌、商品的开发。

5.1.导入数据

首先导入SQL 文档:商城SQL.note 链接:http://note.youdao.com/noteshare?id=b41558310d69342554f1fe8f80c977b2&sub=C10B736123364057AB0676C328A9F56F

我们先看商品分类表:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
CREATE TABLE `tb_category` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '类目id',
  `name` varchar(20) NOT NULL COMMENT '类目名称',
  `parent_id` bigint(20) NOT NULL COMMENT '父类目id,顶级类目填0',
  `is_parent` tinyint(1) NOT NULL COMMENT '是否为父节点,0为否,1为是',
  `sort` int(4) NOT NULL COMMENT '排序指数,越小越靠前',
  PRIMARY KEY (`id`),
  KEY `key_parent_id` (`parent_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1424 DEFAULT CHARSET=utf8 COMMENT='商品类目表,类目和商品(spu)是一对多关系,类目与品牌是多对多关系';

因为商品分类会有层级关系,因此这里我们加入了parent_id字段,对本表中的其它分类进行自关联。

5.2.页面实现

5.2.1.页面分析

首先我们看下要实现的效果:

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

商品分类之间是会有层级关系的,采用树结构去展示是最直观的方式。

一起来看页面,对应的是/pages/item/Category.vue:

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

页面模板:

代码语言:javascript
复制
<template>
  <v-card>
      <v-flex xs12 sm10>
        <v-tree url="/item/category/list"
                :treeData="treeData"
                :isEdit="isEdit"
                @handleAdd="handleAdd"
                @handleEdit="handleEdit"
                @handleDelete="handleDelete"
                @handleClick="handleClick"
        />
      </v-flex>
  </v-card>
</template>
  • v-card:卡片,是vuetify中提供的组件,提供一个悬浮效果的面板,一般用来展示一组数据。
在这里插入图片描述
在这里插入图片描述
  • v-flex:布局容器,用来控制响应式布局。与BootStrap的栅格系统类似,整个屏幕被分为12格。我们可以控制所占的格数来控制宽度:
在这里插入图片描述
在这里插入图片描述

本例中,我们用sm10控制在小屏幕及以上时,显示宽度为10格

  • v-tree:树组件。Vuetify并没有提供树组件,这个是我们自己编写的自定义组件:
在这里插入图片描述
在这里插入图片描述

里面涉及一些vue的高级用法,大家暂时不要关注其源码,会用即可。

5.2.2.树组件的用法

也可参考课前资料中的:《自定义Vue组件的用法.md》

这里我贴出树组件的用法指南。

属性列表:

属性名称

说明

数据类型

默认值

url

用来加载数据的地址,即延迟加载

String

-

isEdit

是否开启树的编辑功能

boolean

false

treeData

整颗树数据,这样就不用远程加载了

Array

-

这里推荐使用url进行延迟加载,每当点击父节点时,就会发起请求,根据父节点id查询子节点信息

当有treeData属性时,就不会触发url加载

远程请求返回的结果格式:

代码语言:javascript
复制
[
    { 
        "id": 74,
        "name": "手机",
        "parentId": 0,
        "isParent": true,
        "sort": 2
	},
     { 
        "id": 75,
        "name": "家用电器",
        "parentId": 0,
        "isParent": true,
        "sort": 3
	}
]

事件:

事件名称

说明

回调参数

handleAdd

新增节点时触发,isEdit为true时有效

新增节点node对象,包含属性:name、parentId和sort

handleEdit

当某个节点被编辑后触发,isEdit为true时有效

被编辑节点的id和name

handleDelete

当删除节点时触发,isEdit为true时有效

被删除节点的id

handleClick

点击某节点时触发

被点击节点的node对象,包含完整的node信息

完整node的信息

回调函数中返回完整的node节点会包含以下数据:

代码语言:javascript
复制
{
    "id": 76, // 节点id
    "name": "手机", // 节点名称
    "parentId": 75, // 父节点id
    "isParent": false, // 是否是父节点
    "sort": 1, // 顺序
    "path": ["手机", "手机通讯", "手机"] // 所有父节点的名称数组
}

5.3.实现功能

5.3.1.url异步请求

给大家的页面中,treeData是假数据,我们删除数据treeData属性,只保留url看看会发生什么:

代码语言:javascript
复制
<v-tree url="/item/category/list"
        :isEdit="isEdit"
        @handleAdd="handleAdd"
        @handleEdit="handleEdit"
        @handleDelete="handleDelete"
        @handleClick="handleClick"
        />

刷新页面,可以看到:

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

页面中的树没有了,并且发起了一条请求:http://localhost/api/item/category/list?pid=0

大家可能会觉得很奇怪,我们明明是使用的相对路径,讲道理发起的请求地址应该是:

http://manage.leyou.com/item/category/list

但实际却是:

http://localhost/api/item/category/list?pid=0

这是因为,我们有一个全局的配置文件,对所有的请求路径进行了约定:

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

路径是localhost,并且默认加上了/api的前缀,这恰好与我们的网关设置匹配,我们只需要把地址改成网关的地址即可,因为我们使用了nginx反向代理,这里可以写域名。

接下来,我们要做的事情就是编写后台接口,返回对应的数据即可。

5.3.2.实体类

ly-item-interface中添加category实体类:

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

内容:

代码语言:javascript
复制
@Table(name="tb_category")
public class Category {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long id;
	private String name;
	private Long parentId;
	private Boolean isParent; // 注意isParent生成的getter和setter方法需要手动加上Is
	private Integer sort;
	// getter和setter略
}

需要注意的是,这里要用到jpa的注解,因此我们在ly-item-iterface中添加jpa依赖

代码语言:javascript
复制
<dependency>
    <groupId>javax.persistence</groupId>
    <artifactId>persistence-api</artifactId>
    <version>1.0</version>
</dependency>

5.3.3.controller

编写一个controller一般需要知道四个内容:

  • 请求方式:决定我们用GetMapping还是PostMapping
  • 请求路径:决定映射路径
  • 请求参数:决定方法的参数
  • 返回值结果:决定方法的返回值

在刚才页面发起的请求中,我们就能得到绝大多数信息:

在这里插入图片描述
在这里插入图片描述
  • 请求方式:Get
  • 请求路径:/api/item/category/list。其中/api是网关前缀,/item是网关的路由映射,真实的路径应该是/category/list
  • 请求参数:pid=0,根据tree组件的说明,应该是父节点的id,第一次查询为0,那就是查询一级类目
  • 返回结果:?? 根据前面tree组件的用法我们知道,返回的应该是json数组: [ { "id": 74, "name": "手机", "parentId": 0, "isParent": true, "sort": 2 }, { "id": 75, "name": "家用电器", "parentId": 0, "isParent": true, "sort": 3 } ] 对应的java类型可以是List集合,里面的元素就是类目对象了。也就是List<Category>

添加Controller:

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

controller代码:

代码语言:javascript
复制
@Controller
@RequestMapping("category")
public class CategoryController {

    @Autowired
    private CategoryService categoryService;

    /**
     * 根据parentId查询类目
     * @param pid
     * @return
     */
    @RequestMapping("list")
    public ResponseEntity<List<Category>> queryCategoryListByParentId(@RequestParam(value = "pid", defaultValue = "0") Long pid) {
        try {
            if (pid == null || pid.longValue() < 0){
                // pid为null或者小于等于0,响应400
                return ResponseEntity.badRequest().build();
            }
            // 执行查询操作
            List<Category> categoryList = this.categoryService.queryCategoryListByParentId(pid);
            if (CollectionUtils.isEmpty(categoryList)){
                // 返回结果集为空,响应404
                return ResponseEntity.notFound().build();
            }
            // 响应200
            return ResponseEntity.ok(categoryList);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 响应500
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }
}

5.3.4.service

一般service层我们会定义接口和实现类,不过这里我们就偷懒一下,直接写实现类了:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
@Service
public class CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    /**
     * 根据parentId查询子类目
     * @param pid
     * @return
     */
    public List<Category> queryCategoryListByParentId(Long pid) {
        Category record = new Category();
        record.setParentId(pid);
        return this.categoryMapper.select(record);
    }
}

5.3.5.mapper

我们使用通用mapper来简化开发:

代码语言:javascript
复制
public interface CategoryMapper extends Mapper<Category> {
}

要注意,我们并没有在mapper接口上声明@Mapper注解,那么mybatis如何才能找到接口呢?

我们在启动类上添加一个扫描包功能:

代码语言:javascript
复制
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.leyou.item.mapper") // mapper接口的包扫描
public class LeyouItemServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(LeyouItemServiceApplication.class, args);
    }
}

5.3.6.启动并测试

我们不经过网关,直接访问:http://localhost:8081/category/list

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

然后试试网关是否畅通:http://api.leyou.com/api/item/category/list

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

一切OK!

然后刷新后台管理页面查看:

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

发现报错了!

浏览器直接访问没事,但是这里却报错,什么原因?

请看下一篇 跨域问题

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 5.实现商品分类查询
    • 5.1.导入数据
      • 5.2.页面实现
        • 5.2.1.页面分析
        • 5.2.2.树组件的用法
      • 5.3.实现功能
        • 5.3.1.url异步请求
        • 5.3.2.实体类
        • 5.3.3.controller
        • 5.3.4.service
        • 5.3.5.mapper
        • 5.3.6.启动并测试
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档