@EnableDiscoveryClient
//由于我们在common工程里面引入了数据库的依赖,网关工程中没有进行配置,这里将其忽略,否则会报错误信息
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GulimallGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallGatewayApplication.class, args);
}
}
②. 在nacos配置中心中配置如下文件
③. bootstrap.yml
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: 3fa6c8bc-2d25-4824-9773-ca6e14a42308
file-extension: yaml
application:
name: gulimall-gateway
spring:
cloud:
gateway:
routes:
- id: test_route1
uri: http://localhost:7000
predicates:
- Path=/coupon/coupon/test/**
CREATE TABLE `pms_category` (
`cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
`name` char(50) DEFAULT NULL COMMENT '分类名称',
`parent_cid` bigint(20) DEFAULT NULL COMMENT '父分类id',
`cat_level` int(11) DEFAULT NULL COMMENT '层级',
`show_status` tinyint(4) DEFAULT NULL COMMENT '是否显示[0-不显示,1显示]',
`sort` int(11) DEFAULT NULL COMMENT '排序',
`icon` char(255) DEFAULT NULL COMMENT '图标地址',
`product_unit` char(50) DEFAULT NULL COMMENT '计量单位',
`product_count` int(11) DEFAULT NULL COMMENT '商品数量',
PRIMARY KEY (`cat_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1433 DEFAULT CHARSET=utf8mb4 COMMENT='商品三级分类';
②. 导入数据(将sql脚本导入进来)
③. 使用java8新特性查找三级联洞并封装成树形结构
@RestController
@RequestMapping("product/category")
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 查出所有分类、以及子分类,以树形结构组装起来
*/
@RequestMapping("/list/tree")
//@RequiresPermissions("product:category:list")
public R list(){
List<CategoryEntity> entities = categoryService.listWithTree();
return R.ok().put("data", entities);
}
}
@Override
public List<CategoryEntity> listWithTree() {
//1、查出所有分类
List<CategoryEntity> entities = baseMapper.selectList(null);
//2、组装成父子的树形结构
//2.1)、找到所有的一级分类
List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->
categoryEntity.getParentCid() == 0
).map((menu)->{
menu.setChildren(getChildrens(menu,entities));
return menu;
}).sorted((menu1,menu2)->{
return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
}).collect(Collectors.toList());
return level1Menus;
}
//递归查找所有菜单的子菜单
private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){
List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
return categoryEntity.getParentCid() == root.getCatId();
}).map(categoryEntity -> {
//1、找到子菜单
categoryEntity.setChildren(getChildrens(categoryEntity,all));
return categoryEntity;
}).sorted((menu1,menu2)->{
//2、菜单的排序
return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
}).collect(Collectors.toList());
return children;
}
@Data
@TableName("pms_category")
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显示]
*/
@TableLogic(value = "1",delval = "0")
private Integer showStatus;
/**
* 排序
*/
private Integer sort;
/**
* 图标地址
*/
private String icon;
/**
* 计量单位
*/
private String productUnit;
/**
* 商品数量
*/
private Integer productCount;
@TableField(exist = false)
private List<CategoryEntity>children;
}
@EnableDiscoveryClient
@SpringBootApplication
public class RenrenApplication {
public static void main(String[] args) {
SpringApplication.run(RenrenApplication.class, args);
}
spring:
application:
name: renren-fast
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
# bootstrap.properties
spring.application.name=renren-fast
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
①. 启动renren-fast和renren-fast-vue,登录系统后新增分类维护菜单栏
②. 通过角色管理role,看到url的路径是sys/role,在浏览器上将/变成了-(sys/role),打开vscode可以看到关系如下:
③. 在vscode中新建product文件夹,新建category.vue
<template>
<div class="">
<el-tree
:data="data"
:props="defaultProps"
@node-click="handleNodeClick"
>el-tree>
div>
template>
<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
export default {
//import引入的组件需要注入到对象中才能使用
components: {},
data() {
//这里存放数据
return {};
},
//监听属性 类似于data概念
computed: {},
data() {
return {
data: [],
defaultProps: {
children: "children",
label: "label"
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
},
getMenus() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get"
}).then(({ data }) => {
if (data && data.code === 0) {
this.data = data.data;
} else {
this.dataList = [];
}
});
}
},
//生命周期 - 创建完成(可以访问当前this实例)
created() {
this.getMenus();
},
//生命周期 - 挂载完成(可以访问DOM元素)
mounted() {}
};
script>
<style scoped>style>
spring:
cloud:
gateway:
routes:
- id: test_route1
uri: http://localhost:7000
predicates:
- Path=/coupon/coupon/test/**
- id: admin_route
uri: lb://renren-fast
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?>/?.*), /renren-fast/$\{segment}
# 前端项目 /api
# http://localhost:88/api/captcha.jpg?uuid=72b9da67-0130-4d1d-8dda-6bfe4b5f7935
# http://renren-fast:8080/renren-fast/captcha.jpg
②. 什么是跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对js施加的安全限制(ajax可以)
③. 同源策略:是指协议,域名,端囗都要相同,其中有一个不同都会产生跨域
④. 跨域流程:这个跨域请求的实现是通过预检请求实现的,先发送一个OPSTIONS探路,收到响应允许跨域后再发送真实请求
跨域请求流程:
非简单请求(PUT、DELETE)等,需要先发送预检请求
-----1、预检请求、OPTIONS ------>
<----2、服务器响应允许跨域 ------
浏览器 | | 服务器
-----3、正式发送真实请求 -------->
<----4、响应数据 --------------
package com.atguigu.gulimall.gateway.config;
@Configuration // gateway
public class GulimallCorsConfiguration {
@Bean // 添加过滤器
public CorsWebFilter corsWebFilter(){
// 基于url跨域,选择reactive包下的
UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();
// 跨域配置信息
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 允许跨域的头
corsConfiguration.addAllowedHeader("*");
// 允许跨域的请求方式
corsConfiguration.addAllowedMethod("*");
// 允许跨域的请求来源
corsConfiguration.addAllowedOrigin("*");
// 是否允许携带cookie跨域
corsConfiguration.setAllowCredentials(true);
// 任意url都要进行跨域配置
source.registerCorsConfiguration("/**",corsConfiguration);
return new CorsWebFilter(source);
}
}
# 如下的配置在nacos中也进行了配置(从spring 到 port: 88),可以进行注释掉
# 当一个请求过来的时候,会交给网关进行处理,通过一系列的预言,如果预言为真,会转到指定的服务,转到指定服务的时候,会经过一系列的过滤器
spring:
# application:
# name: gulimall-gateway
# cloud:
# nacos:
# discovery:
# server-addr: 127.0.0.1:8848
#server:
# port: 88
cloud:
gateway:
routes:
# 测试网关的功能
- id: test_route1
uri: http://localhost:7001
predicates:
- Path=/coupon/coupon/nacos/config/simple/**
# 商品服务网关配置(注意需要把product_route放在admin_route前面)
# http://localhost:88/api/product/category/list/tree
# http://localhost:10000/product/category/list/tree
- id: product_route
uri: lb://gulimall-product
predicates:
- Path=/api/product/**
filters:
- RewritePath=/api/(?>/?.*), /$\{segment}
- id: admin_route
uri: lb://renren-fast
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?>/?.*), /renren-fast/$\{segment}
# 前端项目 /api
# http://localhost:88/api/captcha.jpg?uuid=72b9da67-0130-4d1d-8dda-6bfe4b5f7935
# http://renren-fast:8080/renren-fast/captcha.jpg
<template>
<div class="">
<el-tree
:data="menus"
:props="defaultProps"
@node-click="handleNodeClick"
>el-tree>
div>
template>
<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
export default {
//import引入的组件需要注入到对象中才能使用
components: {},
data() {
//这里存放数据
return {};
},
//监听属性 类似于data概念
computed: {},
data() {
return {
menus: [],
defaultProps: {
children: "children",
label: "name"
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
},
getMenus() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get"
}).then(({ data }) => {
if (data && data.code === 0) {
this.menus = data.data;
}
});
}
},
//生命周期 - 创建完成(可以访问当前this实例)
created() {
this.getMenus();
},
//生命周期 - 挂载完成(可以访问DOM元素)
mounted() {}
};
script>
<style scoped>style>