SpringCloud(学习 商品服务-三级分类的开发)四


前言

本文主要记录商品服务的开发,以及过程中遇到的知识点等。


一、三级分类

表结构

其中最顶级的parent_cid(父分类id)为0

商品三级分类表


Controller编写

用于返回所有分类以及子分类,以树型结构组装起来

 @RequestMapping("/list/tree")
    public R list(){
    
    
        List<CategoryEntity> entities = categoryService.listWithTree();
        return R.ok().put("data", entities);
    }

Service编写

  • Service接口编写

定义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>
  • 将renren-fast 后台服务注册到注册中心
  • 在网关服务中拦截renren-fast前端请求并控制和修改
spring:
  cloud:
    gateway:
      routes: #是个集合
        - id: admin_route
          uri: lb://renren-fast  #负载均衡到 renren-fast服务 springcloud2020后需要加Loadbalancer的依赖 作为负载均衡
          predicates:
            - Path=/api/**   #‘/api’ 下的所有请求
          filters:
            - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}

在这里插入图片描述


三、网关配置跨域

问题描述:
当在请求登录接口时会发生CORS跨域问题。
不满足同源策略的都会发生跨域问题

同源策略:协议、域名、端口都要相同,其中有一个不同都会产生跨域

CORS跨域问题

跨域流程

跨域访问控制详解

非简单请求会产生CORS问题,其中简单请求是指:

  • GET
  • HEAD
  • POST
  • Content-Type 标头所指定的媒体类型的值仅限于下列三者之一:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded

非简单请求,需要先发送预检请求(OPTIONS)

CORS请求流程

解决跨域

  • 使用nginx部署为同一域

将前端和后端部署在nginx服务器上,当静态请求先给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);
    }
}

四、将分类请求转发给商品服务

  • 将商品服务注册到注册中心
  • 在nacos新建商品服务的命名空间
  • 在网关服务配置转发路由
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>.*),/$\{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();
    }

总结

本文主要讲了商品服务三级分类的相关业务功能开发,以及请求转发、跨域配置等。前端请求先通过网关验证后转发给对应服务,其中网关可对请求做出修改,跨域解决就是通过该方法解决,值得一提的是如果进行跨域,请求会先发送一个预检请求,服务器同意后才能将真正的请求发送给服务器。

猜你喜欢

转载自blog.csdn.net/smznbhh/article/details/131548743