谷粒商城--三级分类
谷粒商城--三级分类
一、树形数据返回
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}