商城三级分类查询
前端
整合 element-ui
1、安装
npm i element-ui -S
2、在 main.js 中写入以下内容:
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';
Vue.use(ElementUI);
new Vue({
el: '#app',
render: h => h(App)
});
3、renren-fastvue已经整合,在src\views\modules\product\下创建category.vue
<!-- 分类维护-三级菜单 -->
<template>
<el-tree :data="menus" :props="defaultProps" ></el-tree>
</template>
<script>
export default {
data() {
return {
menus: [],
defaultProps:{
children:"children",
label:"name"
}
};
},
created () {
this.getMenus();
},
methods: {
getMenus() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get"
}).then(({ data }) => {
console.log("成功获取到菜单数据...", data.data);
this.menus = data.data;
});
},
}
};
</script>
<style lang='scss' scoped>
</style>
属性值参见官网
renren-fast
启动renren-fast前端服务和后端服务创建菜单
后端
Spring gateway
使用Spring gateway网关同一请求到网关再转发到具体服务,具体使用Spring gateway见谷粒商城分布式基础篇三
配置文件
gateway服务application.yml配置文件
spring:
cloud:
gateway:
routes:
- id: product_route
#lb 表示转发至服务 服务也许注册到nacos
uri: lb://mall-product
predicates:
#当请求为指定路径 断言为真 **代表任意 这个路径需往上写提高优先级不被/api/**给拦截
- Path=/api/product/**
filters:
#断言为真,重写路径/api/(?<segment>.*)改为/$\{segment}
#例请求http://localhost:88/api/product/category/list/tree会改为
#http://mall-product端口/product/category/list/tree
- RewritePath=/api/(?<segment>.*),/$\{segment}
- id: admin_route
uri: lb://renren-fast
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}
在这里遇到一个错误,无法实例化renren-fast
是因为renren-fast服务找不到,第一反应是renren-fast服务没有注册到nacos服务,检查注册成功,排除。
检查gatway配置中文配置转发服务是否配置错误,检查成功,排除。
百度有一中情况服务名使用下划线,转发失败,检查为中划线,排除。
最后发现gatway和renren-fast注册nacos不同的命名空间,导致网关找不到服务,改为相同命名空间public,转发成功。
在renrenfast-vue static\config\index.js中修改统一请求url为http://localhost:88/api
/**
* 开发环境
*/
;(function () {
window.SITE_CONFIG = {};
// api接口请求地址
window.SITE_CONFIG['baseUrl'] = 'http://localhost:88/api';
// cdn地址 = 域名 + 版本号
window.SITE_CONFIG['domain'] = './'; // 域名
window.SITE_CONFIG['version'] = ''; // 版本号(年月日时分)
window.SITE_CONFIG['cdnUrl'] = window.SITE_CONFIG.domain + window.SITE_CONFIG.version;
})();
跨域问题
解决跨域问题
项目使用第二种方法:在gatway项目创建跨域配置类
@Configuration
public class MallCorsConfiguration {
@Bean
public CorsWebFilter corsWebFilter() {
//响应式编程
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
//配置跨域
//任意请求头
corsConfiguration.addAllowedHeader("*");
//任意请求方法
corsConfiguration.addAllowedMethod("*");
//任意请求来源
corsConfiguration.addAllowedOrigin("*");
//是否允许携带cookie
corsConfiguration.setAllowCredentials(true);
source.registerCorsConfiguration("/**",corsConfiguration);
return new CorsWebFilter(source);
}
}
需引入第二个响应式包
两次请求
renrenfast后端服务需屏蔽原有配置 io.renren.config.CorsConfig
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package io.renren.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedOrigins("*")
// .allowCredentials(true)
// .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// .maxAge(3600);
// }
}
商品服务
product项目中创建菜单controller
@RestController
@RequestMapping("product/category")
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 查询所有分类以及子分类,以树形结构组装起来
*/
@RequestMapping("/list/tree")
public R list() {
List<CategoryEntity> entities = categoryService.listWithTree();
return R.ok().put("data", entities);
}
}
serviceImpl
@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
IPage<CategoryEntity> page = this.page(
new Query<CategoryEntity>().getPage(params),
new QueryWrapper<CategoryEntity>()
);
return new PageUtils(page);
}
/**
* 查询所有分类以及子分类,以树形结构组装起来
*/
@Override
public List<CategoryEntity> listWithTree() {
//1、查询所有的分类
List<CategoryEntity> allCategory = baseMapper.selectList(null);
//2、组装成父子的树形结构
//2.1、找到所有一级分类
List<CategoryEntity> level1Menus = allCategory.stream().filter(categoryEntity ->
categoryEntity.getParentCid() == 0
).map((menu) -> {
menu.setChildren(getChildren(menu, allCategory));
return menu;
}).sorted((menu1, menu2) -> {
return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
}).collect(Collectors.toList());
return level1Menus;
}
/**
* 递归查找所有菜单的子菜单
*
* @param menu 菜单
* @param allCategory 所有分类
* @return 所有菜单的子菜单
*/
private List<CategoryEntity> getChildren(CategoryEntity menu, List<CategoryEntity> allCategory) {
List<CategoryEntity> children = allCategory.stream().filter(categoryEntity -> {
return categoryEntity.getParentCid().equals(menu.getCatId());
}).map(categoryEntity -> {
categoryEntity.setChildren(getChildren(categoryEntity, allCategory));
return categoryEntity;
}).sorted((menu1, menu2) -> {
return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
}).collect(Collectors.toList());
return children;
}
}