Spring Cloud Gateway

一 什么是Spring Cloud Gateway

网关作为流量的入口,常用的功能包括路由转发,权限校验,限流等。
Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架,定位于取代 Netflix Zuul。相比 Zuul 来说,Spring Cloud Gateway 提供更优秀的性能,更强大的有功能。
Spring Cloud Gateway 是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。
Spring Cloud Gateway 旨在为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等等。
在这里插入图片描述
官网文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

1.1 核心概念

  • 路由(route)
    路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL和配置的路由匹配。
  • 断言(predicates)
    Java8中的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的ServerWebExchange。断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。
  • 过滤器(Filter)
    SpringCloud Gateway中的filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行处理。

1.2 工作原理

Spring Cloud Gateway 的工作原理跟 Zuul 的差不多,最大的区别就是 Gateway 的 Filter 只有 pre 和 post 两种。
在这里插入图片描述
客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关 Web 处理程序,此时处理程序运行特定的请求过滤器链。
过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的前后执行逻辑。所有 pre 过滤器逻辑先执行,然后执行代理请求;代理请求完成后,执行 post 过滤器逻辑。

二 Spring Cloud Gateway快速开始

2.1 环境搭建

  1. 引入依赖
<!-- gateway网关 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency><!-- nacos服务注册与发现 -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

注意:会和spring-webmvc的依赖冲突,需要排除spring-webmvc

  1. 编写yml配置文件
server:port: 8888
spring:application:name: mall-gateway#配置nacos注册中心地址cloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:discovery:locator:# 默认为false,设为true开启通过微服务创建路由的功能,即可以通过微服务名访问服务# http://localhost:8888/mall-order/order/findOrderByUserId/1enabled: true# 是否开启网关    enabled: true 
  1. 测试
    在这里插入图片描述

2.2 路由断言工厂(Route Predicate Factories)配置

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
网关启动日志:

2.2.1 时间匹配

可以用在限时抢购的一些场景中。
在这里插入图片描述

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口predicates:# 测试:http://localhost:8888/order/findOrderByUserId/1# 匹配在指定的日期时间之后发生的请求  入参是ZonedDateTime类型- After=2021-01-31T22:22:07.783+08:00[Asia/Shanghai]

获取ZonedDateTime类型的指定日期时间

ZonedDateTime zonedDateTime = ZonedDateTime.now();//默认时区
// 用指定时区获取当前时间
ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));

设置时间之前发起请求:
在这里插入图片描述
超过设置时间之后再次请求:
在这里插入图片描述

2.2.2 Cookie匹配

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口predicates:# Cookie匹配- Cookie=username, fox

postman测试
在这里插入图片描述
curl测试
在这里插入图片描述

2.2.3 Header匹配

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口predicates:# Header匹配  请求中带有请求头名为 x-request-id,其值与 \d+ 正则表达式匹配#- Header=X-Request-Id, \d+

测试
在这里插入图片描述

2.2.4 路径匹配

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口predicates:# 测试:http://localhost:8888/order/findOrderByUserId/1- Path=/order/**   #Path路径匹配

2.2.5 自定义路由断言工厂

自定义路由断言工厂需要继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。在 apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。
注意: 命名需要以 RoutePredicateFactory 结尾

@Component
@Slf4j
public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {public CheckAuthRoutePredicateFactory() {super(Config.class);}@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {log.info("调用CheckAuthRoutePredicateFactory" + config.getName());if(config.getName().equals("fox")){return true;}return false;}};}/*** 快捷配置* @return*/@Overridepublic List<String> shortcutFieldOrder() {return Collections.singletonList("name");}public static class Config {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}
}

yml中配置

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口predicates:# 测试:http://localhost:8888/order/findOrderByUserId/1- Path=/order/**   #Path路径匹配#自定义CheckAuth断言工厂
#        - name: CheckAuth
#          args:
#            name: fox- CheckAuth=fox   

2.3 过滤器工厂( GatewayFilter Factories)配置

SpringCloudGateway 内置了很多的过滤器工厂,我们通过一些过滤器工厂可以进行一些业务逻辑处理器,比如添加剔除响应头,添加去除参数等
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

2.3.1 添加请求头

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口#配置过滤器工厂filters:- AddRequestHeader=X-Request-color, red  #添加请求头

测试http://localhost:8888/order/testgateway

@GetMapping("/testgateway")
public String testGateway(HttpServletRequest request) throws Exception {log.info("gateWay获取请求头X-Request-color:"+request.getHeader("X-Request-color"));return "success";
}
@GetMapping("/testgateway2")
public String testGateway(@RequestHeader("X-Request-color") String color) throws Exception {log.info("gateWay获取请求头X-Request-color:"+color);return "success";
}

在这里插入图片描述

2.3.2 添加请求参数

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口#配置过滤器工厂filters:- AddRequestParameter=color, blue  # 添加请求参数

测试http://localhost:8888/order/testgateway3

@GetMapping("/testgateway3")
public String testGateway3(@RequestParam("color") String color) throws Exception {log.info("gateWay获取请求参数color:"+color);return "success";
}

在这里插入图片描述

2.3.3 为匹配的路由统一添加前缀

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口#配置过滤器工厂filters:- PrefixPath=/mall-order  # 添加前缀 对应微服务需要配置context-path

mall-order中需要配置

server:servlet:context-path: /mall-order

测试:http://localhost:8888/order/findOrderByUserId/1 ====》 http://localhost:8020/mall-order/order/findOrderByUserId/1

2.3.4 重定向操作

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口#配置过滤器工厂filters:- RedirectTo=302, https://www.baidu.com/  #重定向到百度

测试:http://localhost:8888/order/findOrderByUserId/1

2.3.5 自定义过滤器工厂

继承AbstractNameValueGatewayFilterFactory且我们的自定义名称必须要以GatewayFilterFactory结尾并交给spring管理。

@Component
@Slf4j
public class CheckAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return (exchange, chain) -> {log.info("调用CheckAuthGatewayFilterFactory==="+ config.getName() + ":" + config.getValue());return chain.filter(exchange);};}
}

配置自定义的过滤器工厂

spring:cloud:gateway:#设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一uri: http://localhost:8020  #目标微服务的请求地址和端口#配置过滤器工厂filters:- CheckAuth=fox,

测试
在这里插入图片描述

2.4 全局过滤器(Global Filters)配置

在这里插入图片描述
GlobalFilter 接口和 GatewayFilter 有一样的接口定义,只不过, GlobalFilter 会作用于所有路由。
官方声明:GlobalFilter的接口定义以及用法在未来的版本可能会发生变化。

2.4.1 LoadBalancerClientFilter

LoadBalancerClientFilter 会查看exchange的属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的值(一个URI),如果该值的scheme是 lb,比如:lb://myservice ,它将会使用Spring Cloud的LoadBalancerClient 来将 myservice 解析成实际的host和port,并替换掉 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的内容。
其实就是用来整合负载均衡器Ribbon的

spring:cloud:gateway:routes:- id: order_routeuri: lb://mall-orderpredicates:- Path=/order/**

2.4.2 自定义全局过滤器

@Component
@Order(-1)
@Slf4j
public class CheckAuthFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//校验请求头中的tokenList<String> token = exchange.getRequest().getHeaders().get("token");log.info("token:"+ token);if (token.isEmpty()){return null;}return chain.filter(exchange);}
}@Component
public class CheckIPFilter implements GlobalFilter, Ordered {@Overridepublic int getOrder() {return 0;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {HttpHeaders headers = exchange.getRequest().getHeaders();//模拟对 IP 的访问限制,即不在 IP 白名单中就不能调用的需求if (getIp(headers).equals("127.0.0.1")) {return null;}return chain.filter(exchange);}private String getIp(HttpHeaders headers) {return headers.getHost().getHostName();}
}

2.5 Gateway跨域配置(CORS Configuration)

在这里插入图片描述
通过yml配置的方式
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration

spring:cloud:gateway:globalcors:cors-configurations:'[/**]':allowedOrigins: "*"allowedMethods:- GET- POST- DELETE- PUT- OPTION

通过java配置的方式
在这里插入图片描述

@Configuration
public class CorsConfig {@Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();config.addAllowedMethod("*");config.addAllowedOrigin("*");config.addAllowedHeader("*");UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration("/**", config);return new CorsWebFilter(source);}
}

2.6 gateway整合sentinel限流

https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:

  • route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
  • 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组

2.6.1 快速开始

使用时需引入依赖:

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-spring-cloud-gateway-adapter</artifactId><version>x.y.z</version>
</dependency>

接入sentinel dashboard,添加yml配置

spring:application:name: mall-gateway-sentinel-demo#配置nacos注册中心地址cloud:nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:# 添加sentinel的控制台地址dashboard: 127.0.0.1:8080

使用时只需注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可

@Configuration
public class GatewayConfiguration {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}/*** 限流异常处理器* @return*/@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {// Register the block exception handler for Spring Cloud Gateway.return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}/*** 限流过滤器* @return*/@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}}

用户可以通过 GatewayRuleManager.loadRules(rules) 手动加载网关规则
GatewayConfiguration中添加

@PostConstructpublic void doInit() {//初始化自定义的APIinitCustomizedApis();//初始化网关限流规则initGatewayRules();//自定义限流异常处理器initBlockRequestHandler();}private void initCustomizedApis() {Set<ApiDefinition> definitions = new HashSet<>();ApiDefinition api = new ApiDefinition("user_service_api").setPredicateItems(new HashSet<ApiPredicateItem>() {{add(new ApiPathPredicateItem().setPattern("/user/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));}});definitions.add(api);GatewayApiDefinitionManager.loadApiDefinitions(definitions);}private void initGatewayRules() {Set<GatewayFlowRule> rules = new HashSet<>();//resource:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。//count:限流阈值//intervalSec:统计时间窗口,单位是秒,默认是 1 秒。rules.add(new GatewayFlowRule("order_route").setCount(2).setIntervalSec(1));rules.add(new GatewayFlowRule("user_service_api").setCount(2).setIntervalSec(1));// 加载网关规则GatewayRuleManager.loadRules(rules);}private void initBlockRequestHandler() {BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {HashMap<String, String> result = new HashMap<>();result.put("code",String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));result.put("msg", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(result));}};//设置自定义异常处理器GatewayCallbackManager.setBlockHandler(blockRequestHandler);}

2.6.2 网关流控控制台

Sentinel 1.6.3 引入了网关流控控制台的支持,用户可以直接在 Sentinel 控制台上查看 API Gateway 实时的 route 和自定义 API 分组监控,管理网关规则和 API 分组配置。
在 API Gateway 端,用户只需要在原有启动参数的基础上添加如下启动参数即可标记应用为 API Gateway 类型:

# 注:通过 Spring Cloud Alibaba Sentinel 自动接入的 API Gateway 整合则无需此参数
-Dcsp.sentinel.app.type=1

2.6.3 网关流控实现原理

在这里插入图片描述

2.7 网关高可用

为了保证 Gateway 的高可用性,可以同时启动多个 Gateway 实例进行负载,在 Gateway 的上游使用 Nginx 或者 F5 进行负载转发以达到高可用。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/25805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue项目实战-脑图编辑管理系统kitymind百度脑图

前言 项目为前端vue项目&#xff0c;把kitymind百度脑图整合到前端vue项目中&#xff0c;显示了脑图的绘制&#xff0c;编辑&#xff0c;到处为json&#xff0c;png&#xff0c;text等格式的功能 文章末尾有相关的代码链接&#xff0c;代码只包含前端项目&#xff0c;在原始的…

一百四十六、Xmanager——Xmanager5连接Xshell7并控制服务器桌面

一、目的 由于kettle安装在Linux上&#xff0c;Xshell启动后需要Xmanager。而Xmanager7版本受限、没有免费版&#xff0c;所以就用Xmanager5去连接Xshell7 二、Xmanager5安装包来源 &#xff08;一&#xff09;注册码 注册码&#xff1a;101210-450789-147200 &#xff08…

车载软件架构 —— 闲聊几句AUTOSAR OS(十)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在世,最怕的就是把别人的眼光当成自己生活的唯一标…

【枚举+trie+dfs】CF514 C

Problem - 514C - Codeforces 题意&#xff1a; 思路&#xff1a; 其实是trie上dfs的板题 先把字符串插入到字典树中 对于每次询问&#xff0c;都去字典树上dfs 注意到字符集只有3&#xff0c;因此如果发现有不同的字符&#xff0c;去枚举新的字符 Code&#xff1a; #in…

Excel功能总结

1&#xff09;每一张表格上都打印表头 “页面布局”-->“打印标题”-->页面设置“工作表”页-->打印标题“顶端标题行” 如&#xff1a;固定第1~2行&#xff0c;设置成“$1:$2” 2&#xff09;将页面内容打印在一页【缩印】 1.选好需要打印的区域&#xff0c;“页面布…

AOSP开发——APN配置文件路径

Android1~9&#xff0c;APN配置文件路径&#xff1a; vendor/sprd/telephony-res/apn/apns-conf_8.xml Android10~12&#xff0c;APN配置文件路径&#xff1a; /vendor/sprd/telephony-res/apn/apns-conf_8_v2.xml Android13&#xff0c;APN配置文件路径&#xff1a; /vendor/…

Android安卓实战项目(8)---自行车fitting计算软件(源码在文末)

Android安卓实战项目&#xff08;8&#xff09;—自行车fitting计算软件&#xff08;源码在文末&#x1f415;&#x1f415;&#x1f415;&#xff09; 【bilibili演示地址】 https://www.bilibili.com/video/BV1eu4y1B7yA/?share_sourcecopy_web&vd_sourceb2e9b9ed746ac…

0101docker mysql8镜像主从复制-运维-mysql

1 概述 主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从库服务器&#xff0c;然后在从库上对这些日志重新执行&#xff08;也叫重做&#xff09;&#xff0c;从而使得从库和主库的数据保持同步。 Mysql支持一台主库同时向多台从库进行复制&#xff0c;从库同时可以…

ubuntu调整路由顺序

Ubuntu系统跳转路由顺序 1、安装ifmetric sudo apt install ifmetric2、查看路由 route -n3、把Iface下面的eth1调到第一位 sudo ifmetric eth1 0命令中eth1是网卡的名称&#xff0c;更改网卡eth1的跃点数&#xff08;metric值&#xff09;为0&#xff08;数值越小&#xf…

读发布!设计与部署稳定的分布式系统(第2版)笔记29_控制层下

1. 配置服务 1.1. 配置服务本身就是分布式数据库 1.1.1. 像ZooKeeper和etcd这样的配置服务 1.1.2. 受CAP定理和亚光速通信的限制 1.1.3. 可实现容量扩展&#xff0c;但不具备资源可伸缩性 1.1.4. 也会遭受相同的网络创伤 1.2. 信息并不仅仅从服务流向客户端实例&#xff…

mysql统计近7天数据量,,按时间戳分组

可以使用以下 SQL 语句来统计近7天的数据量&#xff0c;并按时间戳分组。如果某一天没有数据&#xff0c;则将其填充为0。 SELECT DATE_FORMAT(FROM_UNIXTIME(timestamp), %Y-%m-%d) AS date,COUNT(*) AS count FROM table_name WHERE timestamp > UNIX_TIMESTAMP(DATE_SUB…

python调用pytorch的clip模型时报错

使用python调用pytorch中的clip模型时报错&#xff1a;AttributeError: partially initialized module ‘clip’ has no attribute ‘load’ (most likely due to a circular import) 目录 现象解决方案一、查看项目中是否有为clip名的文件二、查看clip是否安装成功 现象 clip…

乍得ECTN(BESC)申请流程

根据TCHAD/CHAD乍得法令&#xff0c;自2013年4月1日起&#xff0c;所有运至乍得的货物都必须申请ECTN(BESC)电子货物跟踪单。如果没有申请&#xff0c;将被视为触犯乍得的条例&#xff0c;并在目的地受到严厉惩罚。ECTN是英语ELECTRONIC CARGO TRACKING NOTE的简称&#xff1b;…

基于Java+SpringBoot+Vue的人事管理系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

Ubuntu 传输文件方法

Ubuntu 传输文件方法 文章目录 Ubuntu 传输文件方法1 scpusage跨越跳板机传输 2 rsync&#xff08;remote sync&#xff09;特性installusage本地拷贝同步将文件从远程机器复制到本地机器将文件从本地机器复制到远程机器通过ssh使用rsync 3 SSHFSusage通过 SSHFS 从远程系统访问…

深挖 Threads App 帖子布局,我进一步加深了对CSS网格布局的理解

当我遇到一个新产品时&#xff0c;我首先想到的是他们如何实现CSS。当我遇到Meta的Threads时也不例外。我很快就探索了移动应用程序&#xff0c;并注意到我可以在网页上预览公共帖子。 这为我提供了一个深入挖掘的机会。我发现了一些有趣的发现&#xff0c;我将在本文中讨论。 …

使用node.js 搭建一个简单的HelloWorld Web项目

文档结构 config.ini #将本文件放置于natapp同级目录 程序将读取 [default] 段 #在命令行参数模式如 natapp -authtokenxxx 等相同参数将会覆盖掉此配置 #命令行参数 -config 可以指定任意config.ini文件 [default] authtokencc83c08d73357802 #对应一条隧…

LeetCode 周赛上分之旅 # 37 多源 BFS 与连通性问题

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…

python高阶技巧

目录 设计模式 单例模式 具体用法 工厂模式 优点 闭包 案例 修改闭包外部变量 闭包优缺点 装饰器 装饰器原理 装饰器写法 递归 递归的调用过程 递归的优缺点 用递归计算阶乘 设计模式 含义&#xff1a;设计模式是一种编程套路&#xff0c;通过这种编程套路可…

AQL品质抽样标准

AQL抽样标准 - 百度文库 Acceptance Quality Limit 接收质量限的缩写&#xff0c;即当一个连续系列批被提交验收时&#xff0c;可允许的最差过程平均质量水平。 AQL普遍应用于各行业产品的质量检验&#xff0c;不同的AQL标准应用于不同物质的检验上。在AQL 抽样时&#xff0c;…