Spring Cloud Gateway 服務網關

????????Spring Cloud Gateway是 Spring Cloud 生態系統中的一個 API 網關服務,用于替換由Zuul開發的網關服務,基于Spring 5.0+Spring Boot 2.0+WebFlux等技術開發,提供了網關的基本功能,例如安全、監控、埋點和限流等,旨在為微服務架構提供一種簡單而有效的統一 API 路由管理方式。

1.網關路由

1.1.認識網關

????????什么是網關?顧明思議,網關就是絡的口。數據在網絡間傳輸,從一個網絡傳輸到另一網絡時就需要經過網關來做數據的路由和轉發以及數據安全的校驗

1.2?Gateway特性

Gateway具有以下主要特性:

  1. 動態路由:能夠匹配任何請求屬性上的路由

  2. 斷言(Predicate)和過濾器(Filter):針對特定路由的靈活配置

  3. 集成 Hystrix 斷路器:提供熔斷功能

  4. 服務發現集成:與 Eureka、Consul 等服務發現組件無縫集成

  5. 請求限流:支持基于多種策略的限流

  6. 路徑重寫:支持請求路徑的重寫

1.3 Gateway相關術語

路由(Route):路由是網關的基本組件,Gateway包含多個路由,每個路由包含唯一的ID(路由編號)、目標URI(即請求最終被轉發到的目的地URI)、路由斷言集合和過濾器集合。

斷言(Predicate):實際上就是Java 8 Function Predicate的斷言功能,即匹配條件,只有滿足條件的請求才會被路由到目標URI。輸入類型是 Spring Framework ServerWebExchange。其允許開發人員自行匹配來自HTTP請求的任何內容,例如HTTP頭或參數。

過濾器(Filter):作用類似于攔截加工,對于經過過濾器的請求和響應,都可以進行修改,例如Spring Framework GatewayFilter實例,可以在發送下游請求之前或之后修改請求和響應。

2.?Gateway工作流程

????????當Gateway客戶端向Gateway服務端發送請求時,請求首先被HttpWebHandlerAdapter提取組裝成網關上下文,然后網關上下文會傳遞到DispatcherHandler中。DispatcherHandler是所有請求的分發處理器,主要負責分發請求對應的處理器,比如將請求分發到對應的RoutePredicateHandlerMapping(路由斷言處理映射器)。路由斷言處理映射器主要用于路由查找,以及找到路由后返回對應的FilterWebHandler。FilterWebHandler主要負責組裝過濾器鏈并調用過濾器執行一系列過濾處理,然后把請求轉到后端對應的代理服務處理,處理完畢之后將反饋信息

Spring Cloud Gateway 的核心流程

客戶端請求 → Gateway Handler Mapping → Gateway Web Handler → 過濾器鏈 → 代理服務

3.?Spring Cloud Gateway案例

案例說明:創建兩個簡單的微服務模擬服務提供者和網關

3.1?父工程

創建父工程統一管理Spring Boot、Spring Cloud和Spring Cloud Alibaba,pom.xml文件代碼如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.hl</groupId><artifactId>shop</artifactId><version>1.0.0</version><packaging>pom</packaging><modules><module>order-consumer</module><module>order-provider</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.12</version><relativePath/></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring-cloud.version>2021.0.3</spring-cloud.version><spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version><spring-boot-web.version>2.7.12</spring-boot-web.version></properties><dependencyManagement><dependencies><!--spring cloud--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!--spring cloud alibaba--><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></dependencies></dependencyManagement><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version></dependency><!--單元測試--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies></project>

3.2 service-provider微服務——服務提供者

在父工程中創建service-provider微服務,整合Nacos注冊中心,并創建一個“/hello”接口來模擬服務提供者。

① 修改pom.xml文件,追加Nacos服務發現組件spring-cloud-starter-alibaba-nacos-discovery,代碼如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hl</groupId><artifactId>shop</artifactId><version>1.0.0</version></parent><artifactId>order-provider</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--nacos 服務注冊發現--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies></project>

② 在service-provider微服務的src/main/resources目錄下創建application.yml文件,配置服務端口號為8081、微服務名為“service-provider”、Nacos注冊中心地址為“localhost:8848”,代碼如下所示。

server:port: 8081
spring:application:name: service-provideprofiles:active: devcloud:nacos:server-addr: localhost:8848 # nacos地址

③ 按照Spring Boot規范創建項目啟動類ServiceProviderApplication,在該啟動類上追加@EnableDiscoveryClient注解(該注解表示向Nacos注冊中心注冊微服務),開啟服務注冊與發現功能,代碼如下所示。

package com.hl;
import com.hl.config.OpenFeignLoggerConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableFeignClients
public class ServiceProviderApplication{public static void main(String[] args) {SpringApplication.run(ServiceProviderApplication.class, args);}
}

④ 創建ProviderController類,在該類上追加@RestController注解,在該類中定義一個hello()方法,返回“hello”及傳進來的實參name。

import org.springframework.web.bind.annotation.GetMapping; 
import org.springframework.web.bind.annotation.RequestParam; 
import org.springframework.web.bind.annotation.RestController; @RestController 
public class ProviderController {@GetMapping("/hello")     public String hello(@RequestParam String name) {return "hello " + name + "!";     } 
} 

3.3 service-gateway微服務——網關

創建微服務service-gateway,并整合到Nacos注冊中心。

① 修改pom.xml文件,追加Nacos服務發現組件spring-cloud-starter-alibaba-nacos-discovery及Gateway依賴spring-cloud-starter-gateway,修改后的pom.xml文件代碼如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hl</groupId><artifactId>shop</artifactId><version>1.0.0</version></parent><artifactId>service-gateway</artifactId> <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--nacos 服務注冊發現--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--負載均衡器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency><!--添加 Gateway依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency></dependencies></project>

② 在service-gateway微服務的src/main/resources目錄下創建application.yml文件,配置服務端口號為8001、微服務名為“service-gateway、Nacos注冊中心地址為“localhost:8848”,spring.cloud.gateway.discovery.locator.enabled為true開啟Gateway服務發現,即Gateway將使用服務發現來動態路由請求,application.yml代碼如下所示。

server:   port: 8001 
spring:   application:     name: service-gateway   cloud:     nacos:       discovery:         server-addr: localhost:8848     gateway:       discovery:         locator:           enabled: true 

③ 按照Spring Boot規范創建項目啟動類ServiceGatewayApplication,在該啟動類上追加@EnableDiscoveryClient注解,開啟服務注冊與發現功能,代碼如下所示。

@SpringBootApplication 
@EnableDiscoveryClient 
public class ServiceGatewayApplication {     public static void main(String[] args) {   SpringApplication.run(ServiceGatewayApplication.class, args);     } 
} 

3.4 測試Gateway路由轉發

????????在IDEA工具中啟動兩個微服務:service-provider和service-gateway。啟動Nacos,訪問http://localhost:8848/nacos,選擇“服務管理”的“服務列表”,可發現service-provider和service-gateway微服務實例,說明微服務已成功注冊到了Nacos注冊中心

????????通過Gateway端口號8001及服務名“service-provider”訪問服務接口,即訪問http://localhost: 8001/service-provider/hello?name=gateway,其中顯示了“hello gateway”。至此基于網關實現了路由轉發。

4.?Gateway過濾器工廠

路由規則的定義語法如下:

spring:cloud:gateway:routes:- id: itemuri: lb://item-servicepredicates:- Path=/items/**,/search/**filters:             - AddRequestHeader=X-Request-red, blue

四個屬性含義如下:

  • id:路由的唯一標示

  • predicates:路由斷言,其實就是匹配條件

  • filters:路由過濾條件

  • uri:路由目標地址,lb://代表負載均衡,從注冊中心獲取目標微服務的實例列表,并且負載均衡選擇一個訪問。

????????過濾器允許以某種方式修改傳入的HTTP請求或傳出的HTTP響應。Gateway內置豐富的過濾器,例如AddRequestHeader、AddRequestParameter、AddResponseHeader、RemoveRequestHeader、StripPrefix、RewritePath、LoadBalancerClientFilter

4.1 AddRequestHeaderGatewayFilterFacotry

????????顧明思議,就是添加請求頭的過濾器,可以給請求添加一個請求頭并傳遞到下游微服務。

使用的使用只需要在application.yaml中這樣配置:

spring:cloud:gateway:routes:- id: test_routeuri: lb://test-servicepredicates:-Path=/test/**filters:- AddRequestHeader=key, value # 逗號之前是請求頭的key,逗號之后是value

如果想要讓過濾器作用于所有的路由,則可以這樣配置:

spring:cloud:gateway:default-filters: # default-filters下的過濾器可以作用于所有路由- AddRequestHeader=key, valueroutes:- id: test_routeuri: lb://test-servicepredicates:-Path=/test/**

5.?Gateway路由斷言工廠

????????Gateway包括很多路由斷言,當HTTP請求進入Gateway之后,由于實際工作中Gateway中存在多個路由,因此路由斷言會根據配置的路由規則對請求進行斷言匹配,若匹配成功則從相應路由轉發。

名稱

說明

示例

After

是某個時間點后的請求

- After=2037-01-20T17:42:47.789-07:00[America/Denver]

Before

是某個時間點之前的請求

- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]

Between

是某兩個時間點之前的請求

- Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]

Cookie

請求必須包含某些cookie

- Cookie=chocolate, ch.p

Header

請求必須包含某些header

- Header=X-Request-Id, \d+

Host

請求必須是訪問某個host(域名)

- Host=**.somehost.org,**.anotherhost.org

Method

請求方式必須是指定方式

- Method=GET,POST

Path

請求路徑必須符合指定規則

- Path=/red/{segment},/blue/**

Query

請求參數必須包含指定參數

- Query=name, Jack或者- Query=name

RemoteAddr

請求者的ip必須是指定范圍

- RemoteAddr=192.168.1.1/24

weight

權重處理

5.1?Header路由斷言

????????Header路由斷言有兩個參數:Header名稱(name)和正則表達式形式的值(value)。該路由斷言用于匹配具有給定名稱且值與正則表達式匹配的HTTP頭。

spring:cloud:gateway:default-filters: # default-filters下的過濾器可以作用于所有路由- AddRequestHeader=key, valueroutes:- id: test_routeuri: lb://test-servicepredicates:             - Header=X-Request-Id, \d+

6. 動態路由

????????路由規則是網關的核心內容,配置在應用的屬性配置文件中,服務啟動的時候將路由規 則加載到內存中,這屬于靜態路由方式。網關的路由配置全部是在項目啟動時由org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator在項目啟動的時候加載,并且一經加載就會緩存到內存中的路由表內(一個Map),不會改變。也不會監聽路由變更,所以我們無法利用配置熱更新來實現路由更新。

????????可采用 Nacos 實現動態路由,把路由更新規則保存在分布式配置 中心 Nacos 中,通過 Nacos 的監聽機制,動態更新每個實例的路由規則。因此,我們必須監聽Nacos的配置變更,然后手動把最新的路由更新到路由表中。

6.1?監聽Nacos配置變更

在Nacos官網中給出了手動監聽Nacos配置變更的SDK:https://nacos.io/zh-cn/docs/sdk.html

監聽配置:

如果希望 Nacos 推送配置變更,可以使用 Nacos 動態監聽配置接口來實現。

public void addListener(String dataId, String group, Listener listener)

請求參數說明:

參數名

參數類型

描述

dataId

string

配置 ID,保證全局唯一性,只允許英文字符和 4 種特殊字符("."、":"、"-"、"_")。不超過 256 字節。

group

string

配置分組,一般是默認的DEFAULT_GROUP。

listener

Listener

監聽器,配置變更進入監聽器的回調函數。

示例代碼:

String serverAddr = "{serverAddr}";
String dataId = "{dataId}";
String group = "{group}";
// 1.創建ConfigService,連接Nacos
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
ConfigService configService = NacosFactory.createConfigService(properties);
// 2.讀取配置
String content = configService.getConfig(dataId, group, 5000);
// 3.添加配置監聽器
configService.addListener(dataId, group, new Listener() {@Overridepublic void receiveConfigInfo(String configInfo) {// 配置變更的通知處理System.out.println("recieve1:" + configInfo);}@Overridepublic Executor getExecutor() {return null;}
});

這里核心的步驟有2步:

  • 創建ConfigService,目的是連接到Nacos

  • 添加配置監聽器,編寫配置變更的通知處理邏輯

第一步:

????????由于我們采用spring-cloud-starter-alibaba-nacos-config自動裝配,因此ConfigService已經在com.alibaba.cloud.nacos.NacosConfigAutoConfiguration中自動創建好了:

NacosConfigManager中是負責管理Nacos的ConfigService的,具體代碼如下:

因此,只要我們拿到NacosConfigManager就等于拿到了ConfigService

第二步:

????????編寫監聽器。雖然官方提供的SDK是ConfigService中的addListener,不過項目第一次啟動時不僅僅需要添加監聽器,也需要讀取配置,因此建議使用的API是這個:

String getConfigAndSignListener(

????????String dataId, // 配置文件id

????????String group, // 配置組,走默認

????????long timeoutMs, // 讀取配置的超時時間

????????Listener listener // 監聽器

) throws NacosException;

????????既可以配置監聽器,并且會根據dataId和group讀取配置并返回。我們就可以在項目啟動時先更新一次路由,后續隨著配置變更通知到監聽器,完成路由更新。

6.2?更新路由

????????Gateway 提供了修改路由的接口 RouteDefinitionWriter,只有通過這個接口才能修改動態路由。

package org.springframework.cloud.gateway.route;import reactor.core.publisher.Mono;/*** @author Spencer Gibb*/
public interface RouteDefinitionWriter {/*** 更新路由到路由表,如果路由id重復,則會覆蓋舊的路由*/Mono<Void> save(Mono<RouteDefinition> route);/*** 根據路由id刪除某個路由*/Mono<Void> delete(Mono<String> routeId);}

這里更新的路由,也就是RouteDefinition,包含下列常見字段:

  • id:路由id

  • predicates:路由匹配規則

  • filters:路由過濾器

  • uri:路由目的地

將來我們保存到Nacos的配置也要符合這個對象結構,將來我們以JSON來保存,格式如下:

{"id": "item","predicates": [{"name": "Path","args": {"_genkey_0":"/items/**", "_genkey_1":"/search/**"}}],"filters": [],"uri": "lb://item-service"
}

以上JSON配置就等同于:

spring:cloud:gateway:routes:- id: itemuri: lb://item-servicepredicates:- Path=/items/**,/search/**

6.3?.實現動態路由

首先引入依賴:

<!--統一配置管理-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--加載bootstrap-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

然后在Nacos控制臺添加路由,路由文件名為gateway-routes.json,類型為json

[{"id": "item","predicates": [{"name": "Path","args": {"_genkey_0":"/items/**", "_genkey_1":"/search/**"}}],"filters": [],"uri": "lb://item-service"}
]

然后在網關gatewayresources目錄創建bootstrap.yaml文件,內容如下:

server:port: 8080 # 端口
spring:application:name: gatewaycloud:nacos:server-addr: localhostconfig:file-extension: yamlshared-configs:- dataId: gateway-routes.json # 動態路由配置

然后,在gateway中定義配置監聽器:

package com.hmall.gateway.route;import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.hmall.common.utils.CollUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {private final RouteDefinitionWriter writer;private final NacosConfigManager nacosConfigManager;// 路由配置文件的id和分組private final String dataId = "gateway-routes.json";private final String group = "DEFAULT_GROUP";// 保存更新過的路由idprivate final Set<String> routeIds = new HashSet<>();@PostConstructpublic void initRouteConfigListener() throws NacosException {// 1.注冊監聽器并首次拉取配置String configInfo = nacosConfigManager.getConfigService().getConfigAndSignListener(dataId, group, 5000, new Listener() {@Overridepublic Executor getExecutor() {return null;}@Overridepublic void receiveConfigInfo(String configInfo) {updateConfigInfo(configInfo);}});// 2.首次啟動時,更新一次配置updateConfigInfo(configInfo);}private void updateConfigInfo(String configInfo) {log.debug("監聽到路由配置變更,{}", configInfo);// 1.反序列化List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);// 2.更新前先清空舊路由// 2.1.清除舊路由for (String routeId : routeIds) {writer.delete(Mono.just(routeId)).subscribe();}routeIds.clear();// 2.2.判斷是否有新的路由要更新if (CollUtils.isEmpty(routeDefinitions)) {// 無新路由配置,直接結束return;}// 3.更新路由routeDefinitions.forEach(routeDefinition -> {// 3.1.更新路由writer.save(Mono.just(routeDefinition)).subscribe();// 3.2.記錄路由id,方便將來刪除routeIds.add(routeDefinition.getId());});}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90920.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90920.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90920.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[數據結構]#6 樹

樹是一種非線性的數據結構&#xff0c;它由節點組成&#xff0c;并且這些節點之間通過邊連接。樹的每個節點可以有一個或多個子節點&#xff0c;并且有一個特殊的節點叫做根節點&#xff08;沒有父節點&#xff09;。樹在計算機科學中應用廣泛&#xff0c;尤其是在數據庫索引、…

車輛網絡安全規定之R155與ISO/SAE 21434

隨著科技的不斷進步&#xff0c;車輛已經從傳統的機械裝置演變為高度智能化的移動終端。現代汽車不僅配備了先進的駕駛輔助系統&#xff08;ADAS&#xff09;、車載信息娛樂系統&#xff08;IVI&#xff09;&#xff0c;還具備聯網功能&#xff0c;能夠實現遠程診斷、自動駕駛、…

Go語言實戰案例-合并多個文本文件為一個

以下是《Go語言100個實戰案例》中的 文件與IO操作篇 - 案例21&#xff1a;合并多個文本文件為一個 的完整內容&#xff0c;適用于初學者學習文件讀取與寫入的綜合運用。&#x1f3af; 案例目標使用 Go 語言將指定目錄下的多個 .txt 文件&#xff0c;合并成一個新的總文件。&…

基坑滲壓數據不準?選對滲壓計能實現自動化精準監測嗎?

一、滲壓監測的背景 滲壓計是一種專門用于測量構筑物內部孔隙水壓力或滲透壓力的傳感器&#xff0c;適用于長期埋設在水工結構物或其它混凝土結構物及土體內&#xff0c;以測量結構物或土體內部的滲透&#xff08;孔隙&#xff09;水壓力。 在水利工程中&#xff0c;大壩、水庫…

Linux網絡:阿里云輕量級應用服務器配置防火墻模板開放端口

1.問題介紹在使用Udp協議或其他協議進行兩臺主機或同一臺主機通信時&#xff0c;常常會出現bind成功&#xff0c;但是在客戶端向服務端發送數據后&#xff0c;服務端無響應的情況&#xff0c;如果使用輕量級應用服務器&#xff0c;大概率是服務器的端口因為防火墻未對公網IP開放…

《 Spring Boot整合多數據源:分庫業務的標準做法》

&#x1f680; Spring Boot整合多數據源&#xff1a;分庫業務的標準做法 文章目錄&#x1f680; Spring Boot整合多數據源&#xff1a;分庫業務的標準做法&#x1f50d; 一、為什么需要多數據源支持&#xff1f;&#x1f4a1; 典型業務場景?? 二、多數據源集成方案對比&#…

前端ApplePay支付-H5全流程實戰指南

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔前言近期公司開展關于蘋果支付的相關業務&#xff0c;與之前不同的是&#xff0c;以前后臺直接獲取第三方Wallet封裝好的接口獲取支付地址&#xff0c;H5頁面直接跳轉使用Appl…

Flink窗口:解鎖流計算的秘密武器

Flink 窗口初識在大數據的世界里&#xff0c;數據源源不斷地產生&#xff0c;形成了所謂的 “無限數據流”。想象一下&#xff0c;網絡流量監控中&#xff0c;每一秒都有海量的數據包在網絡中穿梭&#xff0c;這些數據構成了一個無始無終的流。對于這樣的無限數據流&#xff0c…

Java排序算法之<希爾排序>

目錄 1、希爾排序介紹 1.1、定義 1.2、核心思想 2、希爾排序的流程 第 1 輪&#xff1a;gap 4 第 2 輪&#xff1a;gap 2 第 3 輪&#xff1a;gap 1 3、希爾排序的實現 4、時間復雜度分析 5、希爾排序的優缺點 6、適用場景 前言 希爾排序&#xff08;Shell Sort&…

c++加載qml文件

這里展示了c加載qml文件的三種方式以及qml文件中根節點的訪問準備在創建工程的初期&#xff0c;遇到了一個問題&#xff0c;cmake文件以前都是系統自動生成的&#xff0c;不需要我做過多的操作修改&#xff0c;但是&#xff0c;加載qml的程序主函數是需要用到QGuiApplication&a…

007TG洞察:GPT-5前瞻與AI時代競爭力構建:技術挑戰與落地路徑

最近&#xff0c;GPT-5 即將發布的消息刷爆了科技圈&#xff0c;更讓人期待的是&#xff0c;GPT-6 已經悄悄啟動訓練了&#xff0c;OpenAI 的奧特曼表示對未來1-2年的模型充滿信心&#xff0c;預測AI將進化為能夠發現新知識的“AI科學家”。面對日益強大的通用AI&#xff0c;企…

Windows下編譯OpenVDB

本文記錄在Windows下編譯OpenVDB的流程。 零、環境 操作系統Windows 11VS Code1.92.1Git2.34.1MSYS2msys2-x86_64-20240507Visual StudioVisual Studio Community 2022CMake3.22.1 一、編譯 1.1 下載 git clone https://github.com/AcademySoftwareFoundation/openvdb.git …

react 內置hooks 詳細使用場景,使用案例

useState場景&#xff1a;組件中管理局部狀態&#xff0c;如表單值、開關、計數器等。const [count, setCount] useState(0); return <button onClick{() > setCount(count 1)}>Click {count}</button>;useEffect 場景&#xff1a;組件掛載時執行副作用&#…

從0到1學Pandas(九):Pandas 高級數據結構與操作

目錄一、探秘多級索引1.1 創建多級索引1.2 多級索引操作1.3 索引轉換二、探索 Panel 與 xarray2.1 Panel 數據結構2.2 xarray 庫2.3 高維數據操作三、時間序列高級應用3.1 時區處理3.2 時間序列重采樣與頻率轉換3.3 時間序列分解與預測四、數據透視與重塑高級技巧4.1 復雜透視表…

C# 圖像轉換實戰:Bitmap 轉 BitmapSource 的 2 種方法

C# 圖像轉換實戰:Bitmap 轉 BitmapSource 的 2 種方法 引言 兩種轉換方法的完整實現 1. 基于GDI句柄的直接轉換 (ToBitmapSourceFast) 2. 基于內存流的編碼轉換 (ToBitmapSourceSafe) 方法對比與選型指南 避坑指南 GDI句柄泄漏問題 圖像顯示不完整 多線程訪問圖像引發異常 不同…

Spring Boot 整合 Spring MVC:自動配置與擴展實踐

Spring MVC 作為 Java Web 開發的核心框架&#xff0c;在傳統 SSM 項目中需要大量 XML 配置&#xff08;如 DispatcherServlet、視圖解析器等&#xff09;。而 Spring Boot 通過 "自動配置" 特性&#xff0c;簡化了 Spring MVC 的整合過程&#xff0c;同時保留了靈活…

print(“\033[31m紅\033[32m綠\033[34m藍\033[0m默認色“)

可以讓python的終端字體有著不一樣的顏色。代碼&#xff1a;print("\033[31m紅\033[32m綠\033[34m藍\033[0m默認色")效果&#xff1a;

LNMP-zblog分布式部署

一、準備3臺主機&#xff08;rocky8&#xff09;下載相應服務[rootnginx ~]# yum install -y nginx nfs-utils[rootphp ~]# yum install -y nfs-utils php-mysqlnd php php-fpm[rootmysql ~]# yum install -y mysql-server二、掛載php端[rootphp ~]# vim /etc/exports [rootphp…

常見代碼八股

1. 利用梯度下降法&#xff0c;計算二次函數yx^2x4的最小值 def target_function(x):return x ** 2 x 4def gradient(x):return 2*x 1x_init 10 x x_init steps 100 lr 0.1 for i in range(100):x x - lr*gradient(x)print(f"最小值 f(x) {target_function(x):.4f…

【深入底層】C++開發簡歷4+4技能描述6

簡歷書寫 熟悉C的封裝、繼承、多態&#xff0c;STL常用容器&#xff0c;熟悉C11的Lambda表達式、智能指針等&#xff0c;熟悉C20協程語法&#xff0c;具有良好的編碼習慣與文檔能力。 回答思路 這里是基本上就是要全會&#xff0c;考察的問題也很固定&#xff0c;stl這塊可以定…