本文主要记录商品服务的开发,以及过程中遇到的知识点等。
其中最顶级的parent_cid(父分类id)为0
用于返回所有分类以及子分类,以树型结构组装起来
@RequestMapping("/list/tree")
public R list(){
List<CategoryEntity> entities = categoryService.listWithTree();
return R.ok().put("data", entities);
}
定义listWithTree方法用于返回树型结构
List<CategoryEntity> listWithTree();
@TableField(exist = false) //不是表中的字段,用来标记排除
private List<CategoryEntity>children;
实现类实现方法
@Override
public List<CategoryEntity> listWithTree() {
//1.查出所有分类
List<CategoryEntity>entities = baseMapper.selectList(null);
//2.组装成树形结构
//2.1 找到所有的一级分类
return entities
.stream()//将集合转换为流
.filter(categoryEntity -> categoryEntity.getParentCid() == 0)//过滤最高层菜单
//返回一个新的流
.peek((menu)-> menu.setChildren(getChildrens(menu,entities)))//查找子菜单
.sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))//根据sort字段排序
// 1.toList()转换为List集合(允许重复,有顺序)
// 2.toSet()转换为Set集合(不允许重复,没有顺序)
// 3.joining()直接将结果拼接
// 4.joining(" | ")每个输出结果之间加拼接符号“|”
// 5.joining(" || ", "Start--", "--End")开始头为Start--,结尾为--End,中间用拼接符号“||”
// 6.collectingAndThen()收集后做其它处理
.collect(Collectors.toList());
}
//递归查找所有菜单的子菜单
private List<CategoryEntity>getChildrens(CategoryEntity root,List<CategoryEntity>all){
return all.stream()
.filter(categoryEntity -> Objects.equals(categoryEntity.getParentCid(), root.getCatId()))//比较父与子菜单是否对应
.peek(categoryEntity -> categoryEntity.setChildren(getChildrens(categoryEntity,all)))// 递归找子菜单
.sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))// 根据sort字段排序
.collect(Collectors.toList());
}
Spring Cloud 2020版本以后,默认移除了对Netflix的依赖,其中就包括Ribbon,官方默认推荐使用Spring Cloud Loadbalancer正式替换Ribbon,并成为了Spring Cloud负载均衡器的唯一实现
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
spring:
cloud:
gateway:
routes: #是个集合
- id: admin_route
uri: lb://renren-fast #负载均衡到 renren-fast服务 springcloud2020后需要加Loadbalancer的依赖 作为负载均衡
predicates:
- Path=/api/** #‘/api’ 下的所有请求
filters:
- RewritePath=/api/(?.*),/renren-fast/$\{segment}
问题描述:
当在请求登录接口时会发生CORS跨域问题。
不满足同源策略的都会发生跨域问题
同源策略:协议、域名、端口都要相同,其中有一个不同都会产生跨域
跨域访问控制详解
非简单请求会产生CORS问题,其中简单请求是指:
非简单请求,需要先发送预检请求(OPTIONS)
将前端和后端部署在nginx服务器上,当静态请求先给nginx服务器,再由nginx服务器给前端;当为动态请求时,nginx会将请求转发给网关,然后网关再去找对应服务
添加响应头
这里使用第二种方式
首先在网关服务中创建配置类,并进行配置,最后注入到容器中
@Configuration //配置类标识
public class GuliCorsConfiguration {
@Bean //注入容器
public CorsWebFilter corsWebFilter(){
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
//1.配置跨域
corsConfiguration.addAllowedHeader("*"); //允许哪些头跨域
corsConfiguration.addAllowedMethod("*"); //允许哪些请求跨域
corsConfiguration.addAllowedOriginPattern("*"); //允许哪些请求来源跨域
corsConfiguration.setAllowCredentials(true); //是否允许携带cook进行跨域
source.registerCorsConfiguration("/**",corsConfiguration); //path:进行配置跨域的路径
return new CorsWebFilter(source);
}
}
spring:
cloud:
gateway:
routes: #是个集合
- id: product_route
uri: lb://guli-product #负载均衡到 guli-product服务 springcloud2020后需要加Loadbalancer的依赖 作为负载均衡
predicates:
- Path=/api/product/** #‘/api/product’ 下的所有请求
filters:
- RewritePath=/api/(?.*),/$\{segment} #去除/api/使转发请求正确
配置网关路由时将更为准确的predicates放在上边,范围更广的放在后边,避免转发地址错误
编写删除接口,删除以数组形式将菜单id传入,可适配批量删除和单独删除
/**
* 删除
* @RequestBody 获取请求体
*/
@RequestMapping("/delete")
// @RequiresPermissions("product:category:delete")
public R delete(@RequestBody Long[] catIds){
//categoryService.removeByIds(Arrays.asList(catIds));
//1.判断是否在其他地方被引用
return categoryService.removeMenuByIds(Arrays.asList(catIds));
}
编写新增接口,以菜单实体类的形式传入后保存
/**
* 保存
*/
@RequestMapping("/save")
//@RequiresPermissions("product:category:save")
public R save(@RequestBody CategoryEntity category){
categoryService.save(category);
return R.ok(200,"success");
}
编写批量修改接口
/**
* 批量修改
*/
@RequestMapping("/update/sort")
//@RequiresPermissions("product:category:update")
public R updateSort(@RequestBody CategoryEntity[] category){
categoryService.updateBatchById(Arrays.asList(category));
return R.ok();
}
本文主要讲了商品服务三级分类的相关业务功能开发,以及请求转发、跨域配置等。前端请求先通过网关验证后转发给对应服务,其中网关可对请求做出修改,跨域解决就是通过该方法解决,值得一提的是如果进行跨域,请求会先发送一个预检请求,服务器同意后才能将真正的请求发送给服务器。