谷粒商城-全栈-17 商品服务-三级分类递归树形结构获取及网关路由重写

一、三级分类数据查询

1、导入商品分类数据

向mysql数据库gulimall_pms-pms-category导入商品分类数据pms_catelog.sql

2、创建树形接口

com.atguigu.gulimall.product.controller.CategoryController创建树形分类接口

/**
 * 查询所有分类以及子分类,以树形结构组装起来
 */
@RequestMapping("/list/tree")
public R list(){
    List<CategoryEntity> entityList = categoryService.listWithTree();
    return R.ok().put("data",entityList);
}

com.atguigu.gulimall.product.service.CategoryService创建方法

public interface CategoryService extends IService<CategoryEntity> {

    PageUtils queryPage(Map<String, Object> params);

    List<CategoryEntity> listWithTree();
}

com.atguigu.gulimall.product.entity.CategoryEntity添加属性

@TableField(exist = false)
private List<CategoryEntity> children;

com.atguigu.gulimall.product.service.impl.CategoryServiceImpl实现具体业务

@Override
    public List<CategoryEntity> listWithTree() {

        // 1、查出所有分类
        List<CategoryEntity> entities = baseMapper.selectList(null);
        // System.out.println(entities);

        // 获取父分类
        /**
       List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->
           categoryEntity.getParentCid() == 0
       ).collect(Collectors.toList());
         */

        // 过滤出父分类,然后父分类再通过map获取子分类
        List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->
            categoryEntity.getParentCid() == 0
        ).map((menu) -> {menu.setChildren(getChildrens(menu, entities));
                return menu;
            }).collect(Collectors.toList());

        // System.out.println(level1Menus);

        // 2、组装成父子的树形结构
        return level1Menus;
    }

    /**
     * 递归查找所有菜单的子菜单
     *
     * @param root
     * @param all
     * @return
     */
    private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {
      List<CategoryEntity> children =  all.stream().filter(categoryEntity -> {
            return categoryEntity.getParentCid() == root.getCatId();
        }).map(categoryEngity ->{
            // 1、找到子菜单
          categoryEngity.setChildren(getChildrens(categoryEngity, all));
          return categoryEngity;
      }).sorted((menu1, menu2) ->{
          // 2、菜单的排序
          return (menu1.getSort() == null ? 0 : menu1.getSort())- (menu2.getSort() == null ? 0 : menu2.getSort());
      }).collect(Collectors.toList());

      return children;

    }

启动 gulimall-product 访问 http://localhost:6000/product/category/list/tree

二、配置网关路径

启动renren-fast、renren-fast-vue
登录 http://localhost:8001/#/login

系统管理-菜单管理-新增 目录 “商品系统”
file

系统管理-菜单管理-新增 菜单“分类维护”
file

创建前端vue文件renren-fast-vue\src\views\modules\product\category.vue

<!-- 分类 -->
<template>
  <el-tree :data="menus" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
</template>

<script>
// 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
// 例如:import 《组件名称》 from '《组件路径》';

export default {
  // import引入的组件需要注入到对象中才能使用
  components: {},
  props: {},
  data() {
    return {
      menus: [],
      defaultProps: {
        children: "children",
        label: "name",
      },
    };
  },
  // 监听属性 类似于data概念
  computed: {},
  // 监控data中的数据变化
  watch: {},
  methods: {
    handleNodeClick(data) {
      console.log(data);
    },
    getMenus() {
      this.$http({
        url: this.$http.adornUrl("/product/category/list/tree"),
        method: "get",
      }).then(({ data }) => {
        this.menus = data.data;
      });
    },
  },
  // 生命周期 - 创建完成(可以访问当前this实例)
  created() {
    this.getMenus();
  },
  // 生命周期 - 挂载完成(可以访问DOM元素)
  mounted() {},
  beforeCreate() {}, // 生命周期 - 创建之前
  beforeMount() {}, // 生命周期 - 挂载之前
  beforeUpdate() {}, // 生命周期 - 更新之前
  updated() {}, // 生命周期 - 更新之后
  beforeDestroy() {}, // 生命周期 - 销毁之前
  destroyed() {}, // 生命周期 - 销毁完成
  activated() {}, // 如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style lang="scss" scoped>
//@import url(); 引入公共css类
</style>

修改static\config\index.js的api接口请求地址为网关地址

// api接口请求地址,http://localhost:8888网关GateWay地址
window.SITE_CONFIG['baseUrl'] = 'http://localhost:8888/api';

将renren-fast服务加入到注册中心Nacos

修改renren-fast的pom.xml文件,将renren-fast 也加入到我们的注册中心Nacos

<dependency>
    <groupId>com.atguigu.gulimall</groupId>
    <artifactId>gulimall-common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

修改renren-fast的renren-fast\src\main\resources\application.yml

spring:
  application:
    name: renren-fast
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

启用注册发现功能renren-fast\src\main\java\io\renren\RenrenApplication.java

@EnableDiscoveryClient
@SpringBootApplication
public class RenrenApplication {
  public static void main(String[] args) {
      SpringApplication.run(RenrenApplication.class, args);
  }

}

网关路由转发

修改gulimall-gateway\src\main\resources\application.yml将路由转发至renren-fast微服务

spring:
  cloud:
    gateway:
      routes:
        - id: admin_route
          uri: lb://renren-fast
          predicates:
            - Path=/api/**
          filters:
            - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}

## 前端项定义规则,都带 /api 前缀, lb 表示负载均衡到哪个注册器
## http://localhost:8888/api/captcha.jpg  需要通过注册中心网关8888端口转发到renren-fast 8080端口服务
## http://localhost:8080/renren-fast/captcha.jpg:
## filters 路径重写 /api/ -> /renren-fast/

访问 http://localhost:8001/#/login,能转发请求查看验证码图片,但有跨域问题

Access to XMLHttpRequest at 'http://localhost:8888/api/sys/login' from origin 'http://localhost:8001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

为者常成,行者常至