专栏首页cwl_Java商城项目-实现商品分类查询

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

5.实现商品分类查询

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

  • 一个商品分类下有很多商品
  • 一个商品分类下有很多品牌
  • 而一个品牌,可能属于不同的分类
  • 一个品牌下也会有很多商品

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

5.1.导入数据

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

我们先看商品分类表:

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:

页面模板:

<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加载

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

[
    { 
        "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节点会包含以下数据:

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

5.3.实现功能

5.3.1.url异步请求

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

<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实体类:

内容:

@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依赖

<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代码:

@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层我们会定义接口和实现类,不过这里我们就偷懒一下,直接写实现类了:

@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来简化开发:

public interface CategoryMapper extends Mapper<Category> {
}

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

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

@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!

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

发现报错了!

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

请看下一篇 跨域问题

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 前端基础-文档对象模型 (DOM)

    DOM是JavaScript操作网页的接口,全称为“文档对象模型”(Document Object Model)。 它的作用是将网页转为一个JavaScript...

    cwl_java
  • 软考分类精讲-案例分析题

    cwl_java
  • 大数据-Flume采集文件到HDFS

    需求 比如业务系统使用log4j生成的日志,日志内容不断增加,需要把追加到日志文件中的数据实时采集到 hdfs

    cwl_java
  • 正则化贪心森林(RGF)的入门简介,含案例研究

    作为曾参与机器学习竞赛的数据科学家,我一直在寻找“非主流”的算法。使用这些算法可能不会成为竞争的赢家。但是他们有独特的预测方式。这些算法可以在集成模型中使用,以...

    AiTechYun
  • 【陆勤践行】Python和数据科学的起步指南

    Python拥有着极其丰富且稳定的数据科学工具环境。遗憾的是,对不了解的人来说这个环境犹如丛林一般(cue snake joke)。在这篇文章中,我会一步一步指...

    陆勤_数据人网
  • 对SQL Server 2008 R2感兴趣StreamInsight特性

    SQL Server 2008 R2的十大变化(上),SQL Server 2008 R2的十大变化(下) 这十大特性中我比较感兴趣的是StreamInsigh...

    张善友
  • 第13周Python学习周记

    凌川江雪
  • web渗透测试--防sql注入

    所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露V...

    我被狗咬了
  • 电子商务系统中类别预测的深层次分类(CS IR)

    在电子商务系统中,类别预测是自动预测给定文本的类别。 类别预测问题不同于传统的类别之间没有关系的分类问题,它被认为是一个标准的层次分类问题,因为类别通常被组织成...

    用户7095611
  • 牛吃草问题【公式法】——以粉笔公考广东省考题目为例

    林万程

扫码关注云+社区

领取腾讯云代金券