课堂笔记20230817

亮子 2023-08-17 00:40:30 17383 0 0 0

SpringCloud 组件

  • eureka 注册中心
  • zuul 1.0 网关(Netflix:奈飞公司,生活大爆炸+越狱+纸牌屋)
  • feign/openfeign 远程调用
  • hystrix 熔断器
  • ribbon 负载均衡(客户端负载均衡)
  • spring cloud config 配置中心
  • gateway 网关

SpringCloud Alibaba 组件

  • nacos (注册中心+配置中心)
  • seata 分布式事务
  • sentinel 熔断器

nacos

图片alt

1、先commit
2、再pull
3、最后再修改代码

            <!--nacos的管理依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
<!--        注册中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
<!--        配置中心:相当于从网络上下载配置 文件-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
spring:
  application:
    # spring应用的名称(唯一)
    name: server-shop-user
#  注册到nacos
  cloud:
    # 熔断器
#    sentinel:
#      transport:
#        dashboard: 127.0.0.1:18080
#        port: 8719
    nacos:
#      注册中心
      discovery:
        server-addr: 192.168.80.131:8848  # nacos地址
#      配置中心
      config:
#        配置中心文件后缀
        file-extension: yaml
        server-addr: 192.168.80.131:8848  # config地址
#        共享配置的配置
        shared-configs:
          - data-id: common-email.yaml
#            group: DEFAULT_GROUP

图片alt

  • 实时更新配置
package com.bw2102a.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 军哥
 * @version 1.0
 * @description: BaseController
 * @date 2023/8/14 11:32
 */

@RestController
@Slf4j
@RefreshScope
@RequestMapping(value = "/base")
public class BaseController {

    @Value("${jwt.privateKey}")
    private String tokenKey;

    @GetMapping(value = "/hello")
    public String hello() {
        return "Hello,world!!!";
    }

    @GetMapping(value = "/testConfig")
    public String testConfig() {
        log.info("tokenKey:" + tokenKey);

        return tokenKey;
    }

}

  • 启动错误排查

图片alt

图片alt

文章链接:
https://blog.csdn.net/qq_36740242/article/details/127382804

nacos 配置中心的多环境配置

图片alt

图片alt

图片alt

配置文件中有提到Data ID,Data ID由服务名称-开发环境.后缀名拼接,所以可以创建不同开发环境的配置文件来进行多环境的管理。

  • 添加依赖
  • 修改配置文件:bootstrap.yml
  • 在nacos上添加服务器配置
  • 多环境: dataid-profile.yaml

守卫路由(如果没有登录就跳转到登录页面)

  • 在请求响应拦截器中实现
// file:request.js
// 1、引入axios库
import axios from "axios"
import router from "@/router"

// 2、创建axios实例
const service = axios.create({
    baseURL: '/api',  // api的base_url
    timeout: 5000  // 请求超时时间
})

// 3、请求拦截器
service.interceptors.request.use(
    config => {
        console.log("request url="+config.url)

        // 获取token,如果有token,就放入http的请求头里面
        let token = window.sessionStorage.getItem('token');
        if(token){
            config.headers = {"token":token}
        }

        return config
    },
    error => {
        return Promise.reject(error)
    }
)

// 4、响应拦截器
service.interceptors.response.use(
    response => {
        // 定时刷新token
        console.log(response.data)
        return response
    },
    error => {
       //发生错误时的响应
       if(error.response.status == 401) {
        window.sessionStorage.removeItem('token')
        window.sessionStorage.removeItem('user')
        router.push('/login')
       }

        return Promise.reject(error)
    }
)

export default service
  • 使用守卫路由
import Vue from 'vue'
import Router from 'vue-router'
import list from '@/components/list'
import Login from '@/views/Login'
import Index from '@/views/Index'

Vue.use(Router)

// eslint-disable-next-line no-unused-vars
let router;
// eslint-disable-next-line no-unused-vars
export default router = new Router({
    routes: [
        {
            path: '/',
            name: 'Root',
            component: Index
        },
        {
            path: '/login',
            name: 'Login',
            component: Login
        },
        {
            path: '/index',
            name: 'Index',
            component: Index
        }
    ]
})

// 守卫路由
router.beforeEach((to, from, next) => {

    // 白名单
    if(to.path === '/login' || to.path === '/regist') {
        return next();
    }

    // 检查token,没有token跳转到登录页面
    let token = window.sessionStorage.getItem('token')
    if(token == null) {
        return next({path: '/login'})
    }

    // 有合法token,则跳转目的页面
    next()
})

产品三级菜单的表结构

  • 表结构
CREATE TABLE `tb_product_type` (
  `type_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '类型ID',
  `type_name` varchar(80) NOT NULL DEFAULT '' COMMENT '分类名称',
  `type_pid` int(11) DEFAULT '0' COMMENT '父级ID',
  `type_sort` int(11) DEFAULT '0' COMMENT '显示顺序',
  `deleted` int(2) DEFAULT '0' COMMENT '删除状态0:未删除1:已删除',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`type_id`) USING BTREE,
  KEY `type_pid` (`type_pid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='产品分类表';
  • 实体类定义
package com.bw2102a.vo;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * @author 军哥
 * @version 1.0
 * @description: TreeVo
 * @date 2023/8/17 17:09
 */

@Data
public class TreeVo implements Serializable {
    private String value;
    private String label;
    private List<TreeVo> children;
}
package com.bw2102a.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bw2102a.domain.ResultVo;
import com.bw2102a.pojo.TbProductType;
import com.bw2102a.service.TbProductTypeService;
import com.bw2102a.mapper.TbProductTypeMapper;
import com.bw2102a.vo.TreeVo;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
* @author 33509
* @description 针对表【tb_product_type(产品分类表)】的数据库操作Service实现
* @createDate 2023-08-17 16:58:24
*/
@Service
public class TbProductTypeServiceImpl extends ServiceImpl<TbProductTypeMapper, TbProductType>
    implements TbProductTypeService{

    @Override
    public ResultVo getTypeTree() {

        //--1 查询所有分类
        List<TbProductType> list = this.list();

        //--2 查出来一级菜单
        List<TreeVo> collect = list.stream().filter(item -> {
            if (item.getTypePid().equals(0)) {
                return true;
            } else {
                return false;
            }
        }).map(item -> {
            TreeVo treeVo = new TreeVo();
            treeVo.setLabel(item.getTypeName());
            treeVo.setValue("" + item.getTypeId());

            return treeVo;
        }).collect(Collectors.toList());

        //--3 递归查询
        collect.forEach(item -> {
            subTree(list, item);
        });

        //--4 返回树
        return ResultVo.SUCCESS(collect);
    }

    private void subTree(List<TbProductType> list, TreeVo treeVo) {
        Integer id = Integer.valueOf(treeVo.getValue());

        List<TreeVo> collect = list.stream().filter(item -> {
            if (item.getTypePid().equals(id)) {
                return true;
            } else {
                return false;
            }
        }).map(item -> {
            TreeVo tree = new TreeVo();
            tree.setLabel(item.getTypeName());
            tree.setValue("" + item.getTypeId());

            // 递归调用
            subTree(list, tree);

            return tree;
        }).collect(Collectors.toList());

        if(collect.size() > 0) {
            treeVo.setChildren(collect);
        }
    }
}
  • 返回树的结果

图片alt

{
  "code": 200,
  "msg": null,
  "result": true,
  "data": [
    {
      "value": "1",
      "label": "家用电器",
      "children": [
        {
          "value": "4",
          "label": "电视",
          "children": [
            {
              "value": "6",
              "label": "游戏电视",
              "children": null
            },
            {
              "value": "7",
              "label": "艺术电视",
              "children": null
            }
          ]
        }
      ]
    },
    {
      "value": "2",
      "label": "手机、运营商、数码",
      "children": [
        {
          "value": "8",
          "label": "手机配件",
          "children": [
            {
              "value": "10",
              "label": "手机壳",
              "children": null
            },
            {
              "value": "11",
              "label": "数据线",
              "children": null
            }
          ]
        },
        {
          "value": "9",
          "label": "摄影摄像",
          "children": [
            {
              "value": "12",
              "label": "数码相机",
              "children": null
            },
            {
              "value": "13",
              "label": "微单相机",
              "children": null
            }
          ]
        }
      ]
    },
    {
      "value": "3",
      "label": "电脑、办公",
      "children": [
        {
          "value": "14",
          "label": "电脑整机",
          "children": [
            {
              "value": "16",
              "label": "笔记本",
              "children": null
            },
            {
              "value": "17",
              "label": "游戏本",
              "children": null
            }
          ]
        },
        {
          "value": "15",
          "label": "电脑配件",
          "children": [
            {
              "value": "18",
              "label": "显示器",
              "children": null
            },
            {
              "value": "19",
              "label": "硬盘",
              "children": null
            }
          ]
        }
      ]
    }
  ]
}
  • 代码实现

Stream流操作

  • stream()
  • filter()
  • map()
  • skip()
  • limit()
  • sorted()
  • collect()
  • foreach()
package com.bw2102a;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bw2102a.mapper.TbProductTypeMapper;
import com.bw2102a.pojo.TbProductType;
import com.bw2102a.vo.TreeVo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

/**
 * @author 军哥
 * @version 1.0
 * @description: TestApplication
 * @date 2023/8/18 14:21
 */

@SpringBootTest
public class TestApplication {

    @Autowired
    TbProductTypeMapper tbProductTypeMapper;

    @Test
    public void testType() {
        // 获取一级分类
        List<TbProductType> tbProductTypes = tbProductTypeMapper.selectList(
//                new QueryWrapper<TbProductType>().lambda().eq(TbProductType::getTypePid, 0)
                null
        );

        // 集合(容器):list\set\map
        // list: arraylist\linklist\vector
        // set: hashset\treeset
        // map: hashmap\hashtable\

        // foreach 循环
        tbProductTypes.forEach(item -> {
            System.out.println(item);
        });

        System.out.println("======================");

        tbProductTypes
                .stream()
                .filter(item -> {
            return item.getTypePid() == 0;
        })
                .map(item -> {
                    TreeVo treeVo = new TreeVo();
                    treeVo.setLabel(item.getTypeName());
                    treeVo.setValue(""+item.getTypeId());
                    treeVo.setChildren(null);

                    return treeVo;
                })
//                .skip(1)
//                .limit(1)
                .sorted((x, y) -> {
                    // -1: x<y
                    //  0: x==y
                    //  1: x>y
                    if(Integer.valueOf(x.getValue()) == Integer.valueOf(y.getValue())) {
                        return 0;
                    }
                    else if(Integer.valueOf(x.getValue()) < Integer.valueOf(y.getValue())) {
                        return 2;
                    }
                    else {
                        return -2;
                    }
                })
                .forEach(item -> {
            System.out.println(item);
        });
    }

}