1. Home
  2. ALL

SpringCloud Alibaba微服务商城项目(十二):商品三级分类功能-获取递归树形数据和网关路由设置与跨域

目录:

  1. 获取属性数据接口打通
  2. 网关路由与路径重写
  3. 统一跨域的处理

1. 获取属性数据接口打通

CategoryController:

/**
     * 查出所有分类以及子分类,树形结构返回
     * 1 查出所有数据不需要参数
     */
    @RequestMapping("/list/tree")
    public R list(){
//        PageUtils page = categoryService.queryPage(params);
        List<CategoryEntity> list = categoryService.listWithTree();
        return R.ok().put("data", list);
    }

CategoryServiceImpl (service接口实现类,采用了反应式编程):

 @Override
    public List<CategoryEntity> listWithTree() {
//        1. 查出所有分类
//        baseMapper可以作为CategoryDao使用,其次我们也可以用autowired引入Dao层,第一种baseMapper请看extends ServiceImpl这个类
        List<CategoryEntity> listCats = categoryDao.selectList(null);
//        2. 组装成树形结构

        //2.1 先找到一级分类
//        List<CategoryEntity> level1Menus = listCats.stream().filter(categoryEntity ->
//                categoryEntity.getParentCid() == 0
//        ).collect(Collectors.toList());
        //2.2 类的私有方法找到分类的子分类(递归操作 可能会有好几层)

        List<CategoryEntity> level1Menus = listCats.stream().filter(categoryEntity ->
            categoryEntity.getParentCid() == 0
        ).map(menu -> {
            menu.setChildren(getChildrens(menu, listCats));
            return menu;
        }).sorted((a,b)->{
            return ( a.getSort() == null ? 0 : a.getSort())  - (b.getSort() == null ? 0 : b.getSort());
        }).collect(Collectors.toList());

        return level1Menus;
    }

    private List<CategoryEntity> getChildrens(CategoryEntity main, List<CategoryEntity> all)
    {
        List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
            return categoryEntity.getParentCid() == main.getCatId();
        }).map(categoryEntity -> {
            //1 找到子菜单的子菜单
            categoryEntity.setChildren(getChildrens(categoryEntity,all));
            return categoryEntity;
        }).sorted((a,b)->{
            return ( a.getSort() == null ?  0 : a.getSort() )  - ( b.getSort() == null ? 0 : b.getSort());
        }).collect(Collectors.toList());

        //2 上面是第二步菜单的排序
        return children;
    }

关于反应式编程方法这块我们不做过多讨论,里面有递归的用法,可以摘出来代码仔细研究

测试接口 http://localhost:11000/product/category/list/tree
测试成功
file

2. 网关路由与路径重写

先启动后台的前端项目,我们使用的是renrenfast,启动后地址是8001端口

file

创建商品管理目录

file

在商品管理下面创建分类管理,注意我们的路径是product/category

file

以上的product/category对应的是下面的vue项目文件

file

这个vue里面我们用的是,https://element.eleme.io/#/zh-CN/component/tree elementui里面的树形控件

file

vue的知识这里就不多说了,我们的树形菜单数据是从后端取过来了,所以我们要写请求的函数,下面就是我写的请求函数

  // 获取数据列表
    getMenus () {
        this.dataListLoading = true;
        this.$http({
          url: this.$http.adornUrl('/product/category/list/tree'),
          method: 'get'
        }).then(({data}) => {
          console.log(data)
          this.menus = data.data
          this.dataListLoading = false
        })
    },

这个函数在下面的生命周期里面触发 created函数

file

这个时候问题出现了,我们后台管理是8080端口,产品服务是11000端口,还有其他各种端口的服务,这个时候我们会出现各种问题端口不能对应等等,所以这个时候我们就需要统一的网关中心服务,

首先把renrenfast注册到nacos配置中心,这样网关就能集中调用这些服务了。

file

file

然后,在gateway模块配置路由规则:

我们用的是path predicate这种断言

file

然后我们的改造是下面的路由,意思就是如果路径是/api/开头的,就转发到lb://renren-fast, lb就是负载均衡的意思,renren-fast是服务名字,这个意思就是如果我们有多个服务那个就会从多个服务去负载均衡

这里面还有一个过滤器意思是把/api/ 替换成/renren-fast/

file

要注意前端的配置为/api这种路径规则,和网关的过滤规则一一对应
file

从本质上讲其实就是以下两个链接的转换:

http://localhost:88/api/captcha.jpg ==> http://localhost:8080/renren-fast/captcha

但是我们又遇到新的问题,我们访问的地址是localhost:8001 但是我们接口请求的地址是88端口,这个会造成跨域的问题,接着就是解决跨域的问题


3. 统一跨域的处理

跨域问题可以总结为以下的要点

可以看到很多情况下都会产生跨域问题,那么如何解决跨域问题呢?

file

除了以上的问题,我们项目里面也出现option预检请求(非简单请求put delete等等)非简单请求的option预检请求,请看下面的参考资料

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

浅谈CORS跨域请求的简单请求和非简单请求

file

解决方案1:nginx配置为同一个域

file

解决方案2:添加响应头(对于非简单请求)

file

我们采用第二种方法,在gateway里面配置一个cors的配置:

file

配置代码如下:

package com.wkkmicro.wkkmall.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;

/**
 * description:
 *
 * @author wangpeng
 * @date 2019/01/02
 */
@Configuration
public class WkkmallCorsConfiguration{
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

以上配置好后重启,我们就可以愉快的使用了,

file

原创文章,作者:admin,如若转载,请注明出处:https://www.cxylaowang.com/630.html

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact Us

在线咨询:点击这里给我发消息

邮件:814489173@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code