谷粒商城--三级分类

发布时间 2023-05-26 10:27:36作者: 哔~哔~哔

谷粒商城--三级分类

一、树形数据返回

1、递归查询树形结构商品信息

查询的实体类,要实现树形,实体类需要有pId(父id),nId(子id)加上忽略字段children(子类集合)。

public class CategoryEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 分类id
	 */
	@TableId
	private Long catId;
	/**
	 * 分类名称
	 */
	private String name;
	/**
	 * 父分类id
	 */
	private Long parentCid;
	/**
	 * 层级
	 */
	private Integer catLevel;
	/**
	 * 是否显示[0-不显示,1显示]
	 */
	private Integer showStatus;
	/**
	 * 排序
	 */
	private Integer sort;
	/**
	 * 图标地址
	 */
	private String icon;
	/**
	 * 计量单位
	 */
	private String productUnit;
	/**
	 * 商品数量
	 */
	private Integer productCount;

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

}

2、查询出所有待分类数据

List<CategoryEntity> categoryEntityList = this.lambdaQuery().list();

3、取出一级菜单

List<CategoryEntity> rootEntityList = categoryEntityList.stream()
                .filter(i -> i.getParentCid() == 0) // 取出一级菜单
                .peek(i-> i.setChildren(getChildren(i,categoryEntityList))) // 为每级菜单赋值子菜单
                .peek(i->{if(Objects.isNull(i.getSort())){i.setSort(0);}}) // 空值处理
                .sorted(Comparator.comparing(CategoryEntity::getSort)) // 排序
                .collect(Collectors.toList());

4、递归查询所有菜单的子菜单

private List<CategoryEntity> getChildren(CategoryEntity nowCategory, List<CategoryEntity> categoryEntityList) {
    return categoryEntityList.stream() // 返回子菜单
            .filter(i -> i.getParentCid().equals(nowCategory.getCatId())) // 获取当前菜单的子菜单
            .peek(i->i.setChildren(getChildren(i,categoryEntityList))) // 把获取到的子菜单递归此方法
            .peek(i->{if(Objects.isNull(i.getSort())){i.setSort(0);}}) // 空值处理
            .sorted(Comparator.comparing(CategoryEntity::getSort)) // 排序
            .collect(Collectors.toList());
}

二、配置网关路由与路径重写

1、新建目录菜单

菜单指定路由url

2、创建模块以及对应的vue

<template>
  <div>
    <el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
  </div>
</template>

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

export default {
  name: 'category',
  data () {
    return {
      data: [],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
    }
  },
  // import 引入的组件需要注入到对象中才能使用
  components: {},
  props: {},
  // 方法集合
  methods: {
    handleNodeClick (data) {
      console.log(data)
    },
    getMenus () {
      this.$http({
        url: this.$http.adornUrl('/product/category/tree/list'),
        method: 'get'
      }).then(({data}) => {
        console.log(data)
        // this.data = data.data
      })
    }
  },
  // 生命周期 - 创建之前
  beforeCreate () {
  },
  // 生命周期 - 创建完成(可以访问当前this 实例)
  created () {
    this.getMenus()
  }
}
</script>

<style scoped>
</style>

3、修改index.js中基础路径

// api接口请求地址
window.SITE_CONFIG['baseUrl'] = 'http://localhost:8080/renren-fast';

此时发送的http请求路径不符合要求

http://localhost:8080/renren-fast/product/category/list/tree

修改api请求接口为网关地址方便访问各种服务,进行扩展

// api接口请求地址
window.SITE_CONFIG['baseUrl'] = 'http://localhost:88/api'

此时实际请求的地址(如验证码)

http://localhost:88/api/captcha.jpg?uuid=a73e24f4-1dce-4aa3-8842-639e79c510ce

4、后台注册nacos

直接请求的网关的相关内容,我们希望的时网关给我们进行路由转发到对应的服务中,而不是直接处理我们的请求。

要想网关给我们做转发,需要网关知道这个服务,将他添加到nacos中。

  • 依赖

  • bootstrap.yml

  • 主启动类 @EnableDiscoveryClient

5、路由转发配置

spring:
  application:
    name: gulimall-gateway
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        namespace: df63e8e1-2b80-42b5-9db0-8aaa4ba6bac3
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: admin-router #id唯一
          uri: lb://renren-fast # 路由转发的地址 lb:表示负载均衡到转发的地址
          predicates: # 断言
            - Path=/api/** # 断言规则: 路径中包含api

此时请求验证码接口404

http://localhost:88/api/captcha.jpg?uuid=02fa4bdd-020d-4774-873a-3e16cfa64286

网关进行转发后,实际请求的服务接口为

http://renren-fast:8080/api/captcha.ipg?uuid=02fa4bdd-020d-4774-873a-3e16cfa64286

默认需要的访问接口为

http://renren-fast:8080/renren-fast/captcha.ipg?uuid=02fa4bdd-020d-4774-873a-3e16cfa64286

6、断言匹配后使用过滤器重写请求路径

spring:
  application:
    name: gulimall-gateway
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        namespace: df63e8e1-2b80-42b5-9db0-8aaa4ba6bac3
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: admin-router 
          uri: lb://renren-fast
          predicates:
            - Path=/api/**
          filters:
            - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}
            # 匹配api开头的路径重写为renren-fast路径
            # 后面的renren-fast 是servlet的请求地址前缀

此时请求验证码接口正常返回

此时发现跨域问题

三、跨域配置

nginx代理配置跨域

网关配置跨域处理

@Configuration
public class GulimallCorsConfiguration {
    @Bean
    public CorsWebFilter corsWebFilter(){
        System.out.println("加载跨域");
        CorsConfiguration corsConfiguration = new CorsConfiguration();

        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();

        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);

        return new CorsWebFilter(urlBasedCorsConfigurationSource);
    }
}

注释人人自带跨域

四、前端页面请求树形结构数据

1、网关路由配置

配置网关路由到product服务

范围小的路由应该写在前面,否则去product的请求会被转发到admin后台服务

spring:
  application:
    name: gulimall-gateway
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        namespace: df63e8e1-2b80-42b5-9db0-8aaa4ba6bac3
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: product-router #id唯一
          uri: lb://gulimall-product
          predicates:
            - Path=/api/product/**
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}
        - id: admin-router #id唯一
          uri: lb://renren-test
          predicates:
            - Path=/api/**
          filters:
            - RewritePath=/api/(?<segment>.*),/renren-test/$\{segment}