SpringCloud (Learning Commodity Services-Development of Three-Level Classification) IV


foreword

This article mainly records the development of commodity services and the knowledge points encountered in the process.


First and third class classification

Table Structure

Among them, the top parent_cid (parent classification id) is 0

Commodity three-level classification table


Controller writing

Used to return all categories and subcategories, assembled in a tree structure

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

Service writing

  • Service interface writing

Define the listWithTree method to return a tree structure

 List<CategoryEntity> listWithTree();
  • Entity class joins subclass collection attribute
	@TableField(exist = false) //不是表中的字段,用来标记排除
	private List<CategoryEntity>children;
  • Implementation class implementation method

    • Query all categories
    • Filter out top-level categories
    • Pass the remaining categories into the method for recursive search submenu
 @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());
    }

tree structure return


Second, the request is forwarded through the gateway

After the Spring Cloud 2020 version, the dependence on Netflix is ​​removed by default, including Ribbon. The official default recommendation is to use Spring Cloud Loadbalancer to officially replace Ribbon, and it has become the only implementation of Spring Cloud load balancer.

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-loadbalancer</artifactId>
		</dependency>
  • Register the renren-fast background service to the registration center
  • Intercept renren-fast front-end requests in the gateway service and control and modify
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}

insert image description here


3. Gateway configuration across domains

Problem description:
CORS cross-domain problems will occur when requesting the login interface.
Cross-domain problems will occur if the same-origin policy is not satisfied

Same-origin policy : the protocol, domain name, and port must be the same, and any difference in one of them will result in cross-domain

CORS cross domain problem

cross domain process

Detailed cross-domain access control

Non-simple requests will cause CORS problems, where simple requests refer to:

  • GET
  • HEAD
  • POST
  • The value of the media type specified by the Content-Type header is limited to one of the following three:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded

Not a simple request, you need to send a preflight request (OPTIONS) first

CORS request process

Solve cross-domain

  • Deploy as same domain with nginx

Deploy the front-end and back-end on the nginx server, when the static request is sent to the nginx server first, and then the nginx server sends it to the front-end; when it is a dynamic request, nginx will forward the request to the gateway, and then the gateway will find the corresponding service

nginx solves cross-domain

  • Configure the request header through the gateway to enable the server to allow cross-domain

Add response header

Add cross-origin request header


Here use the second way

First create a configuration class in the gateway service, configure it, and finally inject it into the container

@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);
    }
}

4. Forward the classification request to the commodity service

  • Register goods and services to the registry
  • Create a namespace for commodity services in nacos
  • Configure forwarding routes on the gateway service
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放在上边,范围更广的放在后边,避免转发地址错误

5. Delete the third-level classification

Write the delete interface, and delete the menu id in the form of an array, which can be adapted to batch delete and individual delete

/**
     * 删除
     * @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));
    }

6. Add three levels of classification

Write a new interface, pass it in as a menu entity class and save it

/**
     * 保存
     */
    @RequestMapping("/save")
    //@RequiresPermissions("product:category:save")
    public R save(@RequestBody CategoryEntity category){
    
    
		categoryService.save(category);

        return R.ok(200,"success");
    }

Seven, edit the three-level classification

Write batch modification interface

 /**
     * 批量修改
     */
    @RequestMapping("/update/sort")
    //@RequiresPermissions("product:category:update")
    public R updateSort(@RequestBody CategoryEntity[] category){
    
    
        categoryService.updateBatchById(Arrays.asList(category));

        return R.ok();
    }

Summarize

This article mainly talks about the development of related business functions for the three-level classification of goods and services, as well as request forwarding and cross-domain configuration. The front-end request is first verified by the gateway and then forwarded to the corresponding service. The gateway can modify the request. The cross-domain solution is solved through this method. It is worth mentioning that if the cross-domain is performed, the request will first send a pre-check request, and the server Only after agreeing can the real request be sent to the server.

Guess you like

Origin blog.csdn.net/smznbhh/article/details/131548743