Youzi的知识库 - 2022年3月
type: channel
link: https://knowledge.autisn.com/index.php/2022/03
description: 关于一个菜鸟的成长过程
items: 跨域
items: 遍历多级菜单
items: Git 把master分支代码复制到自己需要的分支
items: SpringCloud Gateway
items: Nacos配置中心
items: Nacos注册中心
items: SpringCloud-OpenFeign远程调用
items: Docker安装MySQL和Redis
items: Docker的安装
items: Docker安装阿里云镜像加速

跨域
type: item
date: 2022-03-29T15:44:00+08:00
description: 1.什么是跨域跨域：指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的，是浏览器对JavaScript施加的安全限制同源策略：指的是协议，域名，端口都要相同，其中一个不同都会产生跨域2.跨域流程非简单请求（PUT,DELETE）等，需要发下哦那个预检请求关键词：Request Method : OPTIONS3.解决跨域3.1使用Nginx部署为同一域3.2配置当次请求允许跨域(添加响应头)Access-Control-Allow-Origin:支持哪些来源的请求跨域Access-Control-Allow-Methods:支持哪些方法跨域Access-Control-Allow-Credentials:跨域请求默认不包含cookie，设置为true可以包含cookieAccess-Control-Expose-Headers:跨域请求暴露的字段CROS请求时，XMLHttpRequest对象的getResponseHeader（）方法只能拿到6个基本字段；Cache-Control、Content-Language、Content-Type、Espires、Last-Modified、Pragma。如果想拿到其他字段，就必须在Access-Control-Expose-Headers里面指定。Access-Control-Max-Age:表明该相应的有效时间为多少秒。在有效时间内，浏览器无须为统一请求再次发起预检请求。请注意，浏览器自身维护了一个最大有效时间，如果该首部字段的值超过了最大有效时间，将不会生效。package com.youzi.gulimall.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; /** * @author youzi */ @Configuration public class GuliMallCorsConfiguration { @Bean public CorsWebFilter corsWebFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); //1、配置跨域 //允许哪些头跨域 corsConfiguration.addAllowedHeader("*"); //允许哪些请求方式跨域 corsConfiguration.addAllowedMethod("*"); //允许哪个请求来源跨域 corsConfiguration.addAllowedOriginPattern("*"); //允许携带cookie跨域 corsConfiguration.setAllowCredentials(true); source.registerCorsConfiguration("/**",corsConfiguration); return new CorsWebFilter(source); } }

遍历多级菜单
type: item
date: 2022-03-23T14:59:00+08:00
description: 1.entity增加字段/** * 所有的子分类 * @TableField(exist = false)表示这个在表的字段里面不存在 */ @TableField(exist = false) private List<CategoryEntity> children;2.service写方法/** * 遍历菜单树结构 * @return */ List<CategoryEntity> listWithTree();3.serviceimpl写业务@Override public List<CategoryEntity> listWithTree() { //1.查出所有分类 List<CategoryEntity> entities = baseMapper.selectList(null); //2.组装成父子的树型结构 //2.1找到所有的一级分类 List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity -> categoryEntity.getParentCid() == 0 ) .map((menu)->{menu.setChildren(getChildrens(menu,entities)); return menu;}) .sorted((menu1,menu2)->{return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());}) .collect(Collectors.toList()); return level1Menus; } /** * 递归查找所有菜单的子菜单 * 获取某一个菜单的子菜单 * @param root 当前菜单 * @param all 所有菜单 * @return */ private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){ List<CategoryEntity> children = all.stream().filter(categoryEntity -> { return categoryEntity.getParentCid().equals(root.getCatId()); }).map(categoryEntity -> { //1.找到子菜单 categoryEntity.setChildren(getChildrens(categoryEntity, all)); return categoryEntity; }).sorted((menu1, menu2) -> { //2.菜单的排序 getSort()可能为空，所以需要处理一下，不处理为空指针异常 return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort()); }).collect(Collectors.toList()); return children; }4.controller层/** * 查出所有分类以及子分类，以树型结构组装起来 */ @RequestMapping("/list/tree") public R list(){ List<CategoryEntity> entities = categoryService.listWithTree(); return R.ok().put("data", entities); }5.表结构/* Navicat Premium Data Transfer Source Server : youzi Source Server Type : MySQL Source Server Version : 50736 Source Host : 106.13.234.61:3306 Source Schema : gulimall_pms Target Server Type : MySQL Target Server Version : 50736 File Encoding : 65001 Date: 23/03/2022 14:54:14 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for…

Git 把master分支代码复制到自己需要的分支
type: item
date: 2022-03-22T09:17:00+08:00
description: 1.先切换到主分支(master)git checkout master2.拉取远程仓库的代码(保证代码是最新的)git pull3.切换到需要合并的分支git checkout 分支名4.将主分支中的代码merge到需要合并的分支中git merge master5.使用上传命令push上去git push origin 分支名

SpringCloud Gateway
type: item
date: 2022-03-20T16:18:00+08:00
description: 1.Gateway是什么SpringCloud Gateway 作为 SpringCloud 官方推出的第二代网关,网关作为流量的入口，常用功能包括路由转发、权限校验、限流控制等。2.核心概念路由。路由是网关最基础的部分，路由信息有一个 ID、一个目的 URL、一组断言和一组 Filter 组成。如果断言路由为真，则说明请求的 URL 和配置匹配断言。Java8 中的断言函数。Spring Cloud Gateway 中的断言函数输入类型是 Spring5.0 框 架中的 ServerWebExchange。Spring Cloud Gateway 中的断言函数允许开发者去定义匹配 来自于 http request 中的任何信息，比如请求头和参数等。、过滤器。一个标准的 Spring webFilter。Spring cloud gateway 中的 filter 分为两种类型的 Filter，分别是 Gateway Filter 和 Global Filter。过滤器 Filter 将会对请求和响应进行修改 处3.使用3.1添加依赖<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>3.2增加application.yml文件内容spring: cloud: gateway: #路由 routes: # - 代表的是一个数组 - id: test_route #地址 uri: https://www.baidu.com #断言：路径相匹配时进行路由 predicates: #Query是固定写法 url是参数名称，baidu是参数值 - Query=url,baidu - id: qq_route uri: https://www.qq.com predicates: - Query=url,qq

Nacos配置中心
type: item
date: 2022-03-18T17:09:00+08:00
description: 1.如何使用Nacos作为配置中心统一管理配置1.1引入Nacos作为配置中心统一管理配置<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency>1.2创建一个bootstrap.properties文件#配置中心的名字 spring.application.name=gulimall-coupon #Nacos的端口 spring.cloud.nacos.config.server-addr=127.0.0.1:88481.3需要给配置中心默认添加一个叫数据集(Data Id) gulimall-coupon.properties。默认规则，模块名.properties1.4给 模块名.properties添加任何配置1.5动态获取配置@RefreshScope @RestController @RequestMapping("coupon/coupon") public class CouponController { @Value("${coupon.user.name}") private String name; @Value("${coupon.user.age}") private Integer age; @RequestMapping("/test") public R test(){ return R.ok().put("name",name).put("age",age); } }1.6访问http://localhost:7000/coupon/coupon/test {"msg":"success","code":0,"name":"zhangsan","age":18}2.进阶2.1命名空间 : 配置隔离;默认 : public(保留空间);默认新增的所有配置都在public空间.1).开发，测试，生产:利用命名空间来做环境隔离注意： 在bootstrap.properties，配置上，需要使用的哪个命名空间下的配置，spring.cloud.nacos.config.namespace=a68a2339-6658-4433-945e-a0c50031aa002).每一个微服务之间互相隔离配置，每一个微服务都创建自己的命名空间，只加载自己命名空间下的所有配置2.2.配置集:所有配置的集合 类似application.yml里面的配置2.3配置集ID:类似文件名​ Data Id:类似文件名2.4配置分组：​ 默认所有的配置集都属于：DEFAULT_GROUP​ 每个微服务创建自己的命名空间，使用配置分组区分环境，dev，test，prod​ 分组名配置:spring.cloud.nacos.config.group=dev3.同时加载多个配置集微服务任何配置信息，任何配置文件都可以放在配置中心中只需要在bootstrap.properties说明加载配置中心中哪些配置文件即可@Value,@ConfigurationProperties,以前SpringBoot任何从配置文件中获取值，都能使用。注意：配置中心有的优先使用配置中心中的spring.application.name=gulimall-coupon spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.namespace=5aeff89d-690b-44af-b64e-4669ec1ed93d spring.cloud.nacos.config.group=prod spring.cloud.nacos.config.ext-config[0].data-id= datasource.yml spring.cloud.nacos.config.ext-config[0].group=dev #动态刷新 spring.cloud.nacos.config.ext-config[0].refresh=true spring.cloud.nacos.config.ext-config[1].data-id= mybatis.yml spring.cloud.nacos.config.ext-…

Nacos注册中心
type: item
date: 2022-03-18T16:42:00+08:00
description: 1.引入Nacos Discovery Starter<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>2.application.yml 配置文件中配置 Nacos Server 地址和微服务名称spring: cloud: nacos: discovery: server-addr: 127.0.0.1:88483.本地启动Nacos服务4.使用 @EnableDiscoveryClient 注解开启服务注册与发现功能@MapperScan("com.youzi.gulimall.coupon.dao") @EnableDiscoveryClient @SpringBootApplication public class GulimallCouponApplication { public static void main(String[] args) { SpringApplication.run(GulimallCouponApplication.class, args); } }5.访问http://localhost:8848/nacos 账号密码都是nacos6.得到服务列表7.注意点#这个两个配置不要搞混 #在 bootstrap.properties 中配置 Nacos server 的地址和应用名 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 #在 application.properties 中配置 Nacos server 的地址： spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

SpringCloud-OpenFeign远程调用
type: item
date: 2022-03-18T16:22:00+08:00
description: Feign是一个声明式的HTTP客户端，他的目的就是让远程调用更加简单。给远程服务发的是HTTP请求。1.引入Open-Feign<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>2.编写一个被调用的接口@RestController @RequestMapping("coupon/coupon") public class CouponController { @RequestMapping("/member/list") public R membercoupons(){ CouponEntity couponEntity = new CouponEntity(); couponEntity.setCouponName("100减1"); return R.ok().put("coupons",Arrays.asList(couponEntity)); } }3.远程调用的微服务模块新建一个接口/** * 这是一个声明式的远程调用,编写的路径以及方法名要一致 */ @FeignClient("gulimall-coupon") public interface CouponFeignService { @RequestMapping("/coupon/coupon/member/list") public R membercoupons(); }4.开启远程调用功能@RestController @RequestMapping("member/member") public class MemberController { @Autowired CouponFeignService couponFeignService; @RequestMapping("/coupons") public R test(){ MemberEntity memberEntity = new MemberEntity(); memberEntity.setNickname("柚子"); R membercoupons = couponFeignService.membercoupons(); return R.ok().put("member",memberEntity) .put("coupons",membercoupons.get("coupons")); } }5.启动类添加注解@EnableFeignClientspackage com.atguigu.gulimall.member; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; //开启远程调用的注解 @EnableFeignClients @EnableFeignClients(basePackages = "com.atguigu.gulimall.member.fegin") @MapperScan(basePackages = "com.atguigu.gulimall.member.dao") @EnableDiscoveryClient @SpringBootApplication public class GulimallMemberApplication { public static void main(String[] args) { SpringApplication.run(GulimallMemberApplication.class, args); } }

Docker安装MySQL和Redis
type: item
date: 2022-03-16T15:44:00+08:00
description: 安装MySQL1.拉取MySQL镜像 # mysql:5.7 后面的是版本号 sudo docker pull mysql:5.7 2.启动MySQL容器 # --name指定容器名字 -v目录挂载 -p指定端口映射 -e设置mysql参数 -d后台运行 docker run -p 3306:3306 --name mysql -v /mydata/mysql/log:/var/log/mysql -v /mydata/mysql/data:/var/lib/mysql -v /mydata/mysql/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7 3.配置MySQL # 进入挂载的mysql配置目录 cd /mydata/mysql/conf # 修改配置文件 vi my.cnf # 拷贝以下内容： [client] default-character-set=utf8 [mysql] default-character-set=utf8 [mysqld] init_connect='SET collation_connection = utf8_unicode_ci' init_connect='SET NAMES utf8' character-set-server=utf8 collation-server=utf8_unicode_ci skip-character-set-client-handshake skip-name-resolve # 重启MySQL使配置生效 docker restart mysql安装Redis1.拉取Redis镜像 # redis 不加冒号表示最新版本 docker pull redis 2.启动Redis容器 2.1创建Redis配置文件目录 mkdir -p /mydata/redis/conf touch /mydata/redis/conf/redis.conf 2.2启动Redis容器 docker run -p 6379:6379 --name redis \ -v /mydata/redis/data:/data \ -v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \ -d redis redis-server /etc/redis/redis.conf 3.配置Redis持久化 echo "appendonly yes" >> /mydata/redis/conf/redis.conf # 重启生效 docker restart redis容器随Docker启动自动运行# mysql docker update mysql --restart=always # redis docker update redis --restart=always

Docker的安装
type: item
date: 2022-03-16T10:26:00+08:00
description: 卸载旧版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine安装依赖的包sudo yum install -y yum-utilsDocker安装地址sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repoDocker安装sudo yum install docker-ce docker-ce-cli containerd.io检查Docker的版本docker -v启动Dockersudo systemctl start docker查看安装的容器sudo docker imagesDocker设置开机自启sudo systemctl enable docker

Docker安装阿里云镜像加速
type: item
date: 2022-03-16T10:13:00+08:00
description: 第一步sudo mkdir -p /etc/docker第二步sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://aa577fcv.mirror.aliyuncs.com"] } EOF第三步sudo systemctl daemon-reload第四步sudo systemctl restart docker