【Spring Cloud 八】Spring Cloud Gateway網關

gateway網關

  • 系列博客
  • 背景
  • 一、什么是Spring Cloud Gateway
  • 二、為什么要使用Spring Cloud Gateway
  • 三、 Spring Cloud Gateway 三大核心概念
    • 4.1 Route(路由)
    • 4.2 Predicate(斷言)
    • 4.3 Filter(過濾)
  • 五、Spring Cloud Gateway是如何工作的
  • 四、 如何使用Spring Cloud Gateway進行服務路由
    • 4.1搭建服務A
      • pom文件
      • yml配置文件
      • 啟動類
      • controller類
    • 4.2 搭建服務B
      • pom文件
      • yml配置文件
      • 啟動類
      • controller類
    • 4.3搭建Spring Cloud Gateway服務
      • pom文件
      • yml配置文件
      • 啟動類
    • 4.4啟動項目
    • 4.5動態路由
  • 五、gateway過濾器
    • 5.1自定義全局過濾器
  • 六、使用gateway做token校驗
    • 6.1實現的大致流程示意圖:![](https://img-blog.csdnimg.cn/3001fa8b45324a61a95e0c06263528a7.png)
    • 6.2實現代碼
      • gateway服務
        • pom.xml文件
        • TokenCheckFilter類
      • login-service服務
        • pom.xml文件
        • LoginController類
      • 訪問測試
  • 總結
  • 升華

系列博客

【Spring Cloud一】微服務基本知識
【Spring Cloud 三】Eureka服務注冊與服務發現
【Spring Cloud 四】Ribbon負載均衡
【Spring Cloud 五】OpenFeign服務調用
【Spring Cloud 六】Hystrix熔斷
【Spring Cloud 七】Sleuth+Zipkin 鏈路追蹤

背景

在項目中是使用了Gateway做統一的請求的入口,以及統一的跨域處理以及統一的token校驗。但是這些工作都是之前的同事來做的,正好在新項目中也需要使用其進行統一的token校驗。本著對Gateway更精進一步所以博主就對Gateway進行了較為全面的學習了解,包括動態路由、自定義過濾器、token校驗和續活。

一、什么是Spring Cloud Gateway

Spring Cloud Gateway提供一種簡單有效的方法來路由到對應的API上,并可以提供一些額外的功能,安全性、監控、度量、負載等等。

我們可以這樣理解,Spring Cloud Gateway將該項目中所有服務對外提供的API聚集起來,并向外提供唯一的入口,同時提供了一些額外的功能,安全性、監控、度量、負載等等。

沒使用Spring Cloud Gateway 之前的示意圖
在這里插入圖片描述
使用Spring Cloud Gateway之后的示意圖:
在這里插入圖片描述

二、為什么要使用Spring Cloud Gateway

  1. 統一入口并解除客戶端與服務端的耦合:在微服務架構中,每個微服務都有自己入口,在沒有它的時候客戶端需要大量微服務的地址,會照成復雜的客戶端代碼。并且會暴露服務端的細節,如果服務端發生變化,可能會影響到客戶端代碼,導致維護困難。
  2. 動態路由和負載均衡:Spring Cloud GateWay 提供動態路由來應對當;網關來能夠在多個服務實例之間進行負載均衡,提供整個系統的高可用。
  3. 請求過濾:在微服務架構中,可能需要對請求進行鑒權、身份驗證一個中心化的地方來處理這些請求過濾和處理邏輯可以減少重復的代碼和邏輯。
  4. 反應式和高性能:由于微服務架構的復雜性,需要一個能夠處理高并發請求的解決方案,以確保系統在高負載情況下保持穩定。Spring Cloud Gateway是基于webFlux框架實現的,而webFlux框架底層使用了高性能Reactor模式通信框架的Netty。

三、 Spring Cloud Gateway 三大核心概念

4.1 Route(路由)

路由是由一個ID、一個目的URI、一組斷言、一組Filter組成。
如果路由斷言為真,那么說明這個路由被匹配上了。

4.2 Predicate(斷言)

是一個java8函數斷言。輸入類型是一個Spring Framewordk ServerWebExchange。可以讓你匹配HTTP上的任何請求。比如請求頭和參數。

4.3 Filter(過濾)

是Spring WebFilter的實例,Spring Cloud Gateway中的Filter分為兩種,分貝是Gateway Filter和Global Filter(一個是針對某一個路由的filter,例如對某一個接口做限流;一個是針對全局的filter,例如token校驗,ip黑名單)。過濾器Filter將會對請求和響應進行修改處理。

五、Spring Cloud Gateway是如何工作的

Spring 官網
在這里插入圖片描述
客戶端向Spring Cloud Gateway發出請求。如果網關處理器映射器確定請求與路由匹配,則會將其發送到網關web處理器。它通過特定的過濾器鏈來運行請求。過濾器被虛線分割的原因是過濾器可以在發送代理請求之前和之后運行對應的邏輯。

四、 如何使用Spring Cloud Gateway進行服務路由

示例項目示意圖:
在這里插入圖片描述
備注:Eureka的搭建可以參考這篇博客:【Spring Cloud 三】Eureka服務注冊與服務發現

這里之所以使用Eureka是為了之后做動態路由和負載均衡。

4.1搭建服務A

pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.wangwei</groupId><artifactId>login-service</artifactId><version>0.0.1-SNAPSHOT</version><name>login-service</name><description>login-service</description><properties><java.version>8</java.version><spring-cloud.version>Hoxton.SR12</spring-cloud.version></properties><dependencies><!--		<dependency>-->
<!--			<groupId>org.springframework.boot</groupId>-->
<!--			<artifactId>spring-boot-starter-data-redis</artifactId>-->
<!--		</dependency>--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

yml配置文件

server:port: 8081spring:application:name: login-serviceeureka:client:service-url:defaultZone: http://localhost:8761/eurekaregister-with-eureka: true #設置為fasle 不往eureka-server注冊,默認為truefetch-registry: true #應用是否拉取服務列表到本地registry-fetch-interval-seconds: 10 #為了緩解服務列表的臟讀問題,時間越短臟讀越少 性能相應的消耗回答instance: #實例的配置instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}hostname: localhost #主機名稱或者服務ipprefer-ip-address: true #以ip的形式顯示具體的服務信息lease-renewal-interval-in-seconds: 10 #服務實例的續約時間間隔

啟動類

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

controller類

@RestController
public class LoginController {@GetMapping("doLogin")public String doLogin(){return "登陸成功";}
}

4.2 搭建服務B

pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.wangwei</groupId><artifactId>teacher-service</artifactId><version>0.0.1-SNAPSHOT</version><name>teacher-service</name><description>teacher-service</description><properties><java.version>8</java.version><spring-cloud.version>Hoxton.SR12</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

yml配置文件

server:port: 8082spring:application:name: teacher-serviceeureka:client:service-url:defaultZone: http://localhost:8761/eurekaregister-with-eureka: true #設置為fasle 不往eureka-server注冊,默認為truefetch-registry: true #應用是否拉取服務列表到本地registry-fetch-interval-seconds: 10 #為了緩解服務列表的臟讀問題,時間越短臟讀越少 性能相應的消耗回答instance: #實例的配置instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}hostname: localhost #主機名稱或者服務ipprefer-ip-address: true #以ip的形式顯示具體的服務信息lease-renewal-interval-in-seconds: 10 #服務實例的續約時間間隔

啟動類

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

controller類

@RestController
public class TeacherController {@GetMapping("teach")public String teach(){return "教書學習";}
}

4.3搭建Spring Cloud Gateway服務

pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.wangwei</groupId><artifactId>gateway-server</artifactId><version>0.0.1-SNAPSHOT</version><name>gateway-server</name><description>gateway-server</description><properties><java.version>8</java.version><spring-cloud.version>Hoxton.SR12</spring-cloud.version></properties><dependencies>
<!--		<dependency>-->
<!--			<groupId>org.springframework.boot</groupId>-->
<!--			<artifactId>spring-boot-starter-data-redis</artifactId>-->
<!--		</dependency>-->
<!--		<dependency>-->
<!--			<groupId>org.springframework.boot</groupId>-->
<!--			<artifactId>spring-boot-starter-data-redis-reactive</artifactId>-->
<!--		</dependency>--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

yml配置文件

server:port: 81 #?????80spring:application:name: gateway-servercloud:gateway:enabled: trueroutes:- id: login-service-route # 路由的id  保持唯一uri: http://localhost:8081 #uri統一資源標識符  url 統一資源定位符#uri: lb://login-service #??lb負載均衡predicates: # 斷言是給某一個路由來設定的一種匹配規則 默認不能作用在動態路由上- Path=/doLogin # 匹配規則 只要你Path配置上了/doLogin 就往uri轉發并將路徑帶上- id: teacher-service-routeurl:  http://localhost:8082predicates:- Path=/teacheureka:client:service-url:defaultZone: http://localhost:8761/eurekaregister-with-eureka: true #設置為fasle 不往eureka-server注冊,默認為truefetch-registry: true #應用是否拉取服務列表到本地registry-fetch-interval-seconds: 10 #為了緩解服務列表的臟讀問題,時間越短臟讀越少 性能相應的消耗回答instance: #實例的配置instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}hostname: localhost #主機名稱或者服務ipprefer-ip-address: true #以ip的形式顯示具體的服務信息lease-renewal-interval-in-seconds: 10 #服務實例的續約時間間隔

啟動類

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

4.4啟動項目

依次啟動Eureka服務,gateway服務和兩個服務A和服務B。

進行調用服務A和服務B:
如下圖所示通過gateway的ip+端口+路徑調用到對應的服務A中和服務B中。

在這里插入圖片描述

在這里插入圖片描述

4.5動態路由

在微服務中通常一個服務的實例有多個,那我們網關如何做負載均衡呢?
gateway幫我們做了很多東西,只要我們集成注冊中心(nacos、Eureka、zoomkeeper)并添加對應的配置gateway就可以自動幫我們進行負載均衡。

方式一:
添加對應的配置信息,來開啟動態路由

    gateway:enabled: trueroutes:- id: login-service-route # 路由的id  保持唯一uri: http://localhost:8081 #uri統一資源標識符  url 統一資源定位符#uri: lb://login-service #??lb負載均衡predicates: # 斷言是給某一個路由來設定的一種匹配規則 默認不能作用在動態路由上- Path=/doLogin # 匹配規則 只要你Path配置上了/doLogin 就往uri轉發并將路徑帶上- id: teacher-service-routeuri:  http://localhost:8082predicates:- Path=/teachdiscovery:locator:enabled: true #開啟動態路由  開啟通過應用名稱找到服務的功能lower-case-service-id: true  # 開啟服務名稱小寫

請求服務時需要帶上對應的服務名稱
在這里插入圖片描述

方式二:
添加對應的配置:uri: lb://login-service #lb負載均衡

    gateway:enabled: trueroutes:- id: login-service-route # 路由的id  保持唯一#uri: http://localhost:8081 #uri統一資源標識符  url 統一資源定位符uri: lb://login-service #lb負載均衡predicates: # 斷言是給某一個路由來設定的一種匹配規則 默認不能作用在動態路由上- Path=/doLogin # 匹配規則 只要你Path配置上了/doLogin 就往uri轉發并將路徑帶上- id: teacher-service-routeuri:  http://localhost:8082predicates:- Path=/teach

在這里插入圖片描述

推薦使用方式一進行統一的配置負載均衡。

五、gateway過濾器

過濾器按照作用范圍可以分為兩種,Gateway Filter和Global Filter。

Gateway Filter:網關過濾器需要通過 spring.cloud.routes.filters 配置在具體路由下,只作用在當前路由上或通過 spring.cloud.default-filters 配置在全局,作用在所有路由上。

Global Filter:全局過濾器,不需要配置路由,系統初始化作用在所有路由上。

全局過濾器一般用于:統計請求次數、限流、token校驗、ip黑名單攔截等。

5.1自定義全局過濾器

@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {/*** 過濾的方法* 職責鏈模式* 網關里面有使用 mybatis的二級緩存有變種職責鏈模式* @param exchange* @param chain* @return*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//針對請求的過濾 拿到請求 header url 參數。。。ServerHttpRequest request = exchange.getRequest();//HttpServletRequest 這個是web里面的//ServerHttpRequest webFlux里面 響應式里面的String path=request.getURI().getPath();System.out.println(path);HttpHeaders headers=request.getHeaders();System.out.println(headers);String name = request.getMethod().name();String hostString = request.getHeaders().getHost().getHostString();System.out.println(hostString);//響應相關數據ServerHttpResponse response = exchange.getResponse();//微服務 肯定是前后端分離的 一般前后端通過數據傳輸是json格式//{"code":200,"msg":"ok"}//設置編碼 響應頭response.getHeaders().set("content-type","application/json;charset=utf-8");//組裝業務返回值HashMap<String ,Object> map=new HashMap<>(4);map.put("code", HttpStatus.UNAUTHORIZED.value());map.put("msg","你未授權");ObjectMapper objectMapper=new ObjectMapper();//把一個map轉換為字節byte[] bytes = new byte[0];try {bytes = objectMapper.writeValueAsBytes(map);} catch (JsonProcessingException e) {throw new RuntimeException(e);}//通過buffer工廠將字節數組包裝成一個數據報DataBuffer wrap = response.bufferFactory().wrap(bytes);return response.writeWith(Mono.just(wrap));//放行,到下一個過濾器//return chain.filter(exchange);}/*** 制定順序的方法* 越小越先執行* @return*/@Overridepublic int getOrder() {return 0;}
}

請求接口進行訪問,可以發現當前請求已經被攔截下來。

在這里插入圖片描述

六、使用gateway做token校驗

6.1實現的大致流程示意圖:

6.2實現代碼

gateway服務

pom.xml文件

在pom文件中新增redis的依賴

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

注意博主是在本機安裝的redis所以不需要在服務中添加對應的redis配置。

TokenCheckFilter類

新建TokenCheckFilter類并實現全局過濾器和Ordered

package com.wangwei.gatewayserver.filter;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.Arrays;
import java.util.HashMap;
import java.util.List;@Component
public class TokenCheckFilter implements GlobalFilter, Ordered {/*** 指定好放行的路徑,白名單*/public static final List<String> ALLOW_URL= Arrays.asList("/doLogin","/myUrl");@Autowiredprivate StringRedisTemplate redisTemplate;/*** 和前端約定好 一般放在請求頭類里面一般key為 Authorization value bearer token* 1.拿到請求url* 2.判斷放行* 3.拿到請求頭* 4.拿到token* 5.校驗* 6.放行/攔截* @param exchange* @param chain* @return*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();String path = request.getURI().getPath();if (ALLOW_URL.contains(path)) {return chain.filter(exchange);}//檢查List<String> authorization = request.getHeaders().get("Authorization");if (!CollectionUtils.isEmpty(authorization)){String token = authorization.get(0);if(StringUtils.hasText(token)){//約定好的有前綴的bearer tokenString realToken = token.replaceFirst("bearer ", "");if (StringUtils.hasText(realToken)&&redisTemplate.hasKey(realToken)){return chain.filter(exchange);}}}//攔截ServerHttpResponse response = exchange.getResponse();response.getHeaders().set("content-type","application/json;charset=utf-8");//組裝業務返回值HashMap<String ,Object> map=new HashMap<>(4);map.put("code", HttpStatus.UNAUTHORIZED);map.put("msg","未授權");ObjectMapper objectMapper=new ObjectMapper();//把一個map轉換為字節byte[] bytes = new byte[0];try {bytes = objectMapper.writeValueAsBytes(map);} catch (JsonProcessingException e) {throw new RuntimeException(e);}//通過buffer工廠將字節數組包裝成一個數據報DataBuffer wrap = response.bufferFactory().wrap(bytes);return response.writeWith(Mono.just(wrap));}@Overridepublic int getOrder() {return 0;}
}

login-service服務

pom.xml文件

在pom文件中新增redis的依賴

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

注意博主是在本機安裝的redis所以不需要在服務中添加對應的redis配置。

LoginController類

在LoginController類中新增doLogin方法

@Autowiredpublic StringRedisTemplate redisTemplate;@PostMapping("doLogin")public String doLogin(@RequestBody User user){//tokenString token= UUID.randomUUID().toString();//存起來redisTemplate.opsForValue().set(token,user.toString(), Duration.ofSeconds(7200));return token;}

訪問測試

http://localhost:81/doLogin

由于在gateway將該/doLogin放入了白名單,所以該請求不會進行token校驗,發送請求成功之后會返回token
在這里插入圖片描述
訪問http://localhost:81/teach,并在請求頭中添加token,最后可以看到請求訪問成功。

在這里插入圖片描述

如果我們不在請求頭中添加對應的token或者token為錯誤token,那么gateway會將請求進行攔截。

在這里插入圖片描述

總結

  1. gateway在微服務中起到了很重要的作用,作為項目請求的統一入口。
  2. gateway也體現了我們軟件設計的復用思想,可以統一進行跨域處理,進行token校驗。
  3. gateway比較重要的一塊是關于他的過濾器,通過實現過濾器的接口,可以自定義過濾器,提供了很強大的可擴展支持

升華

通過學習gateway不光是學習gateway更重要的是學習軟件設計思想。

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

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

相關文章

如何使用Kali Linux進行密碼破解?

今天我們探討Kali Linux的應用&#xff0c;重點是如何使用它來進行密碼破解。密碼破解是滲透測試中常見的任務&#xff0c;Kali Linux為我們提供了強大的工具來幫助完成這項任務。 1. 密碼破解簡介 密碼破解是一種滲透測試活動&#xff0c;旨在通過不同的方法和工具來破解密碼…

力扣初級算法(數組拆分)

力扣初級算法&#xff08;數組拆分&#xff09; 每日一算法&#xff1a; 力扣初級算法&#xff08;數組拆分&#xff09; 學習內容&#xff1a; 1.問題描述 給定長度為 2n 的整數數組 nums &#xff0c;你的任務是將這些數分成 n 對, 例如 (a1, b1), (a2, b2), …, (an, bn) …

機器人CPP編程基礎-03變量類型Variables Types

機器人CPP編程基礎-02變量Variables 全文AI生成。 C #include<iostream>using namespace std;main() {int a10,b35; // 4 bytescout<<"Value of a : "<<a<<" Address of a : "<<&a <<endl;cout<<"Val…

[Openwrt]一步一步搭建MT7981A uboot、atf、openwrt-21.02開發環境操作說明

安裝ubuntu-18.04 軟件安裝包 ubuntu-18.04-desktop-amd64.iso 修改ubuntu管理員密碼 sudo passwd [sudo] password for w1804: Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully 更新ubuntu源 備份源 sudo cp /etc/apt/so…

CentO7.9安裝Docker

文章目錄 CentO7.9安裝Docker刪除舊版本的Docker安裝Docker倉庫安裝Docker安裝最新版本安裝指定版本 Docker安裝個NGINX查看Docker鏡像運行查看Docker進程查看啟動端口停止Docker容器 CentO7.9安裝Docker 刪除舊版本的Docker sudo yum remove docker \docker-client \docker-…

Vue+ElementUI實現選擇指定行導出Excel

這里記錄一下&#xff0c;今天寫項目時 的一個需求&#xff0c;就是通過復選框選中指定行然后導出表格中選中行的Excel表格 然后這里介紹一個工具箱(模板)&#xff1a;vue-element-admin 將它拉取后&#xff0c;運行就可以看到如下界面&#xff1a; 這里面的很多功能都已經實現…

【NAS群暉drive異地訪問】使用cpolar遠程訪問內網Synology Drive「內網穿透」

文章目錄 前言1.群暉Synology Drive套件的安裝1.1 安裝Synology Drive套件1.2 設置Synology Drive套件1.3 局域網內電腦測試和使用 2.使用cpolar遠程訪問內網Synology Drive2.1 Cpolar云端設置2.2 Cpolar本地設置2.3 測試和使用 3. 結語 前言 群暉作為專業的數據存儲中心&…

jupyter切換conda虛擬環境

環境安裝 conda install nb_conda 進入你想使用的虛擬環境&#xff1a; conda activate your_env_name 在你想使用的conda虛擬環境中&#xff1a; conda install -y jupyter 在虛擬環境中安裝jupyter&#xff1a; conda install -y jupyter 重啟jupyter 此時我們已經把該安裝…

也許你正處于《孤注一擲》中的“團隊”,要留心了

看完這部電影&#xff0c;心情久久不能平靜&#xff0c;想了很多&#xff0c;倒不是擔心自己哪天也成為“消失的yaozi”&#xff0c;而是在想&#xff0c;我們每天所賴以生存的工作&#xff0c;跟電影里他們的工作比&#xff0c;差別在哪里呢&#xff1f; 目錄 1. 產品的本質…

Linux系統下的性能分析命令

在 Linux 系統下&#xff0c;有許多用于性能分析和調試的命令和工具&#xff0c;可以幫助您識別系統瓶頸、優化性能以及調查問題。本文將介紹在性能分析過程中&#xff0c;可能使用到的一些命令。 以下是一些常用的性能分析命令和工具匯總&#xff1a; 命令功能簡述top用于實…

2023-08-16力扣每日一題

鏈接&#xff1a; 2682. 找出轉圈游戲輸家 題意&#xff1a; 環形1到n&#xff0c;從1開始&#xff0c;每次移動 第i次*k &#xff0c;當移動到出現過的序號時停下&#xff0c; 求沒移動到的數字 解&#xff1a; 簡單模擬題&#xff0c;我也以為有數學做法&#xff0c;可…

docker安裝部署

目錄 docker安裝部署 1.環境 2.安裝步驟 1.安裝必要工具 2.配置軟件源 3.修改軟件源 4.更新并下載docker 5.設置開機自啟 3.啟動docker 1.配置docker鏡像加速器 2.啟動服務 docker安裝部署 1.環境 centos7 2.安裝步驟 1.安裝必要工具 yum install -y yum-utils dev…

【QT+ffmpeg】QT+ffmpeg 環境搭建

1.qt下載地址 download.qt.io/archive/ 2. win10sdk 下載 https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ 安裝 debug工具路徑 qtcreater會自動識別 調試器選擇

最長連續序列

題目&#xff1a; 給定一個未排序的整數數組 nums &#xff0c;找出數字連續的最長序列&#xff08;不要求序列元素在原數組中連續&#xff09;的長度。 示例 1&#xff1a; 輸入&#xff1a;nums [100,4,200,1,3,2] 輸出&#xff1a;4 解釋&#xff1a;最長數字連續序列是…

74、75、76——tomcat項目實戰

tomcat項目實戰 tomcat 依賴 java運行環境,必須要有jre , 選擇 jdk1.8 JvmPertest 千萬不能用 kyj易捷支付 項目機器 選擇 一臺機器 ,安裝jdk1.8的機器下載tomcat的包 上傳到機器,解壓tomcattomcat文件 bin文件夾: 啟動文件 堆棧配置文件 catalina.sh JAVA_OPTS="-Xm…

gitlab合并新項目和分支切換

一、新建項目 1、創建空白項目 2、先創建一個群組 3、編寫群組信息 4、創建群組完成以后新建項目 ??????? 二、將代碼推送到gitlab 1、初始化 git init 2、關聯gitlab地址 # 比如:http://192.168.139.128:7070/cloud/obwt_cloud.git git remote add origin <你…

FreeRTOS qemu mps2-an385 bsp 移植制作 :串口打印篇

相關文章 FreeRTOS qemu mps2-an385 bsp 移植制作 &#xff1a;環境搭建篇 FreeRTOS qemu mps2-an385 bsp 移植制作 &#xff1a;系統啟動篇 FreeRTOS qemu mps2-an385 bsp 移植制作 &#xff1a;系統運行篇 開發環境 Win10 64位 VS Code&#xff0c;ssh 遠程連接 ubuntu …

如何使用Python編寫小游戲?

大家好&#xff0c;我是沐塵而生&#xff0c;如果你是一個熱愛編程的小伙伴&#xff0c;又想嘗試游戲開發&#xff0c;那么這篇文章一定能滿足你的好奇心。不廢話&#xff0c;讓我們馬上進入Python游戲開發的精彩世界吧&#xff01; Python游戲開發的魅力 編寫小游戲不僅僅是鍛…

BUUCTF [安洵杯 2019]easy_serialize_php 1 詳細講解

題目來自buuctf&#xff0c;這是一題關于php序列化逃逸的題 1. 題目 題目給出的代碼 <?php$function $_GET[f];function filter($img){$filter_arr array(php,flag,php5,php4,fl1g);$filter /.implode(|,$filter_arr)./i;return preg_replace($filter,,$img); }if($_S…

【重復處理】CRUD接口冪等性處理

保證冪等性的核心思想&#xff1a;通過唯一的業務單號保證冪等 非并發情況下&#xff0c;查詢業務單號有沒有操作過&#xff0c;沒有則執行操作針對第一次執行業務時間&#xff0c;有大量并發情況下&#xff0c;整個操作過程加鎖&#xff0c;通過分布式鎖來加鎖Select操作&…