[Spring] Gateway详解

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (93平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
🐰RabbitMQ(97平均质量分) https://blog.csdn.net/2301_80050796/category_12792900.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. 网关介绍
    • 1.1 问题
    • 1.2 什么是API网关
  • 2. Spring Cloud Gateway
    • 2.1 快速上手
    • 2.2 Route Predicate Factories(路由谓词工厂)
      • 2.2.1 Predicate
      • 2.2.2 Route Predicate Factories
      • 2.2.3 代码演示
    • 2.3 Gateway Filter Factories(网关过滤器工厂)
      • 2.3.1 GatewayFilter
        • 快速上手
        • 常见的GatewayFilter类型
        • Default Filters
      • 2.3.2 GlobalFilter
        • 快速上手
    • 2.4 过滤器的执行顺序
    • 2.5 自定义过滤器
      • 2.5.1 自定义Gateway Filter
        • 定义GatewayFilter
        • 配置过滤器
      • 2.5.2 自定义GlobalFilter
        • 自定义GlobalFilter

1. 网关介绍

1.1 问题

在前面,我们通过Eureka,Nacos解决了服务注册,服务发现的问题,使用Spring Cloud LoadBalance解决了负载均衡的问题,使用OpenFeign解决了远程调用的问题.
但是当前所有微服务的接口都是直接对外暴露的,可以直接通过外部访问.为了保证对外服务的安全性,服务端实现的微服务接口通常都带有一定的权限校验机制.由于使用了微服务,原本⼀个应用的的多个模块拆分成了多个应用,我们不得不实现多次校验逻辑.当这套逻辑需要修改时,我们需要修改多个应用,加重了开发人员的负担.

针对上述的问题,一个最常用的方案就是使用API网关.

比如外部人员去一个公司办理业务,公司需要先核实对方的身份之后再去进行办理,而且公司划分为了多个部门,每个部门都需要先对对方的身份进行核实之后再进行办理.这样的效率是非常低的,
为此我们对此进行了改进,设立前台,统一又前台来进行身份的核实,前台身份校验通过之后,其他部门就可以设置信任,直接办理业务.

1.2 什么是API网关

API网关(简称网关)也是一个服务,通常是后端服务的唯一入口,它的定义类似设计模式中的门面模式.它就类似与整个微服务架构的门面,所有的外部客户访问,都要经过它来进行调度和过滤.
在这里插入图片描述
网关核心功能:

  1. 权限控制: 作为微服务的入口,对于用户进行权限校验,如果校验失败则进行拦截.
  2. 动态路由: 一切请求先经过网关,但是网关不做业务处理,而是根据某种规则把请求转发到某个微服务.
  3. 负载均衡: 当路由的目标服务有多个时,还需要做负载均衡.
  4. 限流: 请求过高时,按照网关中配置微服务能够接受的流量进行放行,避免服务压力过大.

常见的网关实现也有很多种,我们今天要讲的是Spring Cloud Gateway

2. Spring Cloud Gateway

2.1 快速上手

我们通过一下的演示,先来了解网关的基本功能.

  1. 创建网关项目
    API网关也是一个服务
    在这里插入图片描述
  2. 引入网关依赖
<dependencies>
    <!--⽹关-->
    <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>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
</dependencies>
  1. 编写启动类
@SpringBootApplication
public class GateWayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GateWayApplication.class,args);
    }
}
  1. 添加Gateway的路由设置
    创建application.yml文件,添加如下的配置:
server:
  port: 10030
spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/product/**
        - id: order-service
          uri: lb//order-service
          predicates:
            - Path=/order/**

配置解释:

  • id: 自定义路由ID,保持唯一即可.
  • uri: 目标服务地址,支持普通URI以及以及lb://应用注册服务名称.lb表示负载均衡,使用该格式表示从注册中心获取服务地址.
  • predicates: 路由条件,根据匹配的结果决定是否执行该请求路由,上述代码中,我们把符合Path规则的一切请求,都代理到uri参数指定的地址.
  1. 测试
    启动API网关服务
    通过网关服务访问product-service
    http://127.0.0.1:10030/order/select?id=1
    在这里插入图片描述
    url符合yml文件中配置的 /product/** 规则
    通过网关访问服务order-service
    在这里插入图片描述
    url符合yml配置文件中的/order/**规则.

2.2 Route Predicate Factories(路由谓词工厂)

2.2.1 Predicate

Predicate是java8提供一个函数式编程接口,它接受一个参数并返回一个布尔值,用于条件过滤,请求参数的校验.
代码演示:

  1. 定义一个Predicate
public class StringPredicate implements Predicate<String> {
    @Override
    public boolean test(String s) {
        return s.isEmpty();
    }
}
  1. 使用这个Predicate
public static void main(String[] args) {
    Predicate<String> predicate = new StringPredicate();
    System.out.println(predicate.test(""));
    System.out.println(predicate.test("aaaa"));
}

在这里插入图片描述
3. Predicate的其他写法
可以使用匿名内部类的写法

public static void main(String[] args) {
    Predicate<String> predicate = new Predicate<String>() {
        @Override
        public boolean test(String s) {
            return s.isEmpty();
        }
    };
    System.out.println(predicate.test(""));
    System.out.println(predicate.test("aaa"));
}

lambda写法:

public static void main(String[] args) {
    Predicate<String> predicate = s -> s.isEmpty();
    System.out.println(predicate.test(""));
    System.out.println(predicate.test("aaa"));
}
  1. Predicate的其他方法
    在这里插入图片描述

2.2.2 Route Predicate Factories

Route Predicate Factories (路由断言工厂,也称为路由谓词工厂,此处谓词表示一个函数),在SpringCloud Gateway中,Predicate提供了路由规则的匹配机制.
我们在配置文件中写的断言规则只是字符串,这些字符串会被Route Predicate Factory读取并处理,转变为路由判断条件.
比如前面章节配置的Path=/product/**就是通过Path属性来匹配URL前缀是/product的请求.
这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory来实现的.
SpringCloud Gateway默认提供了很多Route Predicate Factory,这些Predicate会分别匹配HTTP请求不同的属性,并且多个Predicate可以通过and逻辑进行组合.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2.3 代码演示

  1. 添加Predicate规则
    在application.yml中添加如下的规则
    在application中添加如下规则
server:
  port: 10030
spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/product/**
            - After=2025-01-30T00:00:00.000+08:00[Asia/Shanghai]
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/order/**
            - After=2025-01-30T00:00:00.000+08:00[Asia/Shanghai]

测试:http://127.0.0.1:10030/product/select?id=1001
在这里插入图片描述
返回了404.把时间改为2025-1-22之后再试.可以正常获取到请求.
在这里插入图片描述

2.3 Gateway Filter Factories(网关过滤器工厂)

Predicate决定了请求由哪一个路由处理,如果在请求之外处理前后需要加上一些逻辑,这就是Filter的作用范围了.
Filter分为两种类型: Pre类型和Post类型.
Pre类型过滤器: 路由处理之前执行(请求转发到后端服务之前),在Pre类型过滤器中可以做鉴权,限流等.
Post类型过滤器: 请求之心完成之后,将结果返回给客户端之前执行.

在这里插入图片描述
SpringCloud Gateway中内置了很多Filter,用于拦截和链式处理web请求,比如权限校验,访问超时等设定.
SpringCloud Gateway从作用范围上,把Filter可分为GatewayFilter和GlobalFilter.
GatewayFilter: 应用到单个路由或者一个分组路由上.
GlobalFilter: 应用到所有路由上,也就是对所有的路由生效.

2.3.1 GatewayFilter

GatewayFilter同Predicate类似,都是在配置文件application.yml中配置.每个过滤器的逻辑都是固定的.比如配置文件中写AddRequestParameter,就可以为所有的请求添加一个参数,我们通过一个例子来演示GatewayFilter该如何使用.

快速上手
  1. 在application文件中添加过滤器.
server:
  port: 10030
spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/product/**
            - After=2025-01-22T00:00:00.000+08:00[Asia/Shanghai]
          filters:
            - AddRequestParameter=name,zhangsan
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/order/**
            - After=2025-01-22T00:00:00.000+08:00[Asia/Shanghai]

该filter值添加在了product-service路由下,因此只对product-service路由生效,也就是/product/**生效.
2. 接收参数并打印
在product-service服务中接收请求的参数,并打印出来.

@RequestMapping("/getParam")
public String getParam(Integer id,String name){
    System.out.println(id);
    System.out.println(name);
    return "接收参数成功";
}
  1. 测试
    发送http://127.0.0.1:10030/product/getParam?id=3
    在这里插入图片描述
    观察控制台日志:
    在这里插入图片描述
常见的GatewayFilter类型

SpringCloud Gateway提供了非常多的Filter.下面列出一些常见过滤器的说明:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
具体可参考Spring官方文档:
https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway/gatewayfilter-factories.html

Default Filters

前面的filter添加在指定路由下,所以只对当前路由生效,若需要对全部路由生效,可以使用spring.cloud.gateway.default-filters这个属性.和上面指定路由下一样,下面都是一个filter的列表.
举例:

spring:
  cloud:
    gateway:
      default-filters:
        - AddResponseHeader=X-Response-Default-Red, Default-Blue
        - PrefixPath=/httpbin

2.3.2 GlobalFilter

GlobalFilter是Spring Cloud Gateway中的全局过滤器,它和GatewayFilter的作用是相同的.GlobalFilter会应用到所有的路由请求上,全局过滤器通常用于实现安全性,性能监控和日志记录等相关的全局功能.
Spring Cloud Gateway内置的全局过滤器也有很多,比如:

  • Gateway Metric Filter:网关指标,提供监控指标
  • Forward Routing Filter: 用于本地forword,请求不转发到下游服务器.
  • LoadBalancer Client Filter:针对下游服务,实现负载均衡.

更多过滤器参考官方文档:https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway/global-filters.html

快速上手
  1. 添加依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. 添加配置
spring:
  cloud:
    gateway:
      metrics:
        enabled: true
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always
    shutdown:
      enabled: true

解释上面的配置信息:

  • spring.cloud.gateway.metrics.enabled: metrics表示指标相关的配置项,enabled 是一个布尔类型的配置参数,当设置为 true 时,意味着开启Spring Cloud Gateway的指标收集功能.开启指标收集功能后,Spring Cloud Gateway会收集一系列与网关运行相关的指标数据.这些指标数据能够帮助开发者和运维人员更好地了解网关的运行状态,性能表现以及流量情况等.
  • management.endpoints.web.exposure.include: "*":该配置用于指定哪些端点(endpoints)可以通过 Web 暴露出去.* 表示所有端点都将被暴露.端点是 Spring Boot Actuator提供的用于监控和管理应用程序的接口,比如健康检查、指标统计、环境变量查看等功能都通过这些端点来实现.
  • management.endpoint.health.show-details: always:此配置针对健康检查端点(health),设置为 always 表示在健康检查响应中始终显示详细信息.
  • management.endpoint.shutdown.enabled: true: 启用了应用程序的关闭端点(shutdown).这允许通过向特定的端点发送请求来优雅地关闭应用程序.
  1. 测试
    重启网关,访问http://127.0.0.1:10030/actuator,显示所有监控的信息链接.
    在这里插入图片描述

2.4 过滤器的执行顺序

一个项目中,即有GatewayFilter,又有GlobalFilter时,执行的先后顺序是什么呢?
请求路由之后,网关会把当前项目中GatewayFilter和GlobalFilter合并到一个过滤器链中,并进行排序,依次执行过滤器.
在这里插入图片描述
每个过滤器都必须指定一个int类型的order值,默认值为0,表示该过滤器的优先级.order值越小,优先级越高,执行顺序越靠前.

  • Filter通过实现Order接口或者添加@Order注解来指定order值.
  • SpringCloud Gateway提供的Filter由Spring指定,用户也可以自定义Filter,由用户指定.
  • 当过滤器的order值一样时,会按照defaultFilter>GatewayFilter>GlobalFilter的顺序来执行.

2.5 自定义过滤器

SpringCloud Gateway提供了过滤器的扩展功能,开发者可以根据实际业务来自定义过滤器,同样自定义过滤器也支持GatewayFilter和GlobalFilter两种.

2.5.1 自定义Gateway Filter

自定义Gateway Filter,需要去实现对应的接口GatewayFilterFactory,SpringBoot默认帮我们实现的抽象类是AbstractGatewayFilterFactory,我们可以直接使用.

定义GatewayFilter

首先针对Filter的配置,使用CustomConfig来定义.

@Data
public class CustomConfig {
    private String Name;
}

继承AbstractGatewayFilterFactory抽象类并重写抽象方法,实现Ordered接口用于指定优先级.

@Component
@Slf4j
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomConfig> implements Ordered {
    /**
     * 执行优先级,LOWEST_PRECEDENCE表示的是最低优先级
     * @return 返回最低优先级
     */
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }

    @Override
    public GatewayFilter apply(CustomConfig config) {
        return new GatewayFilter() {
            /**
             * Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChainchain)
             * ServerWebExchange: HTTP请求-响应交互的契约, 提供对HTTP请求和响应的访问, 服
             务器端请求属性, 请求实例,响应实例等, 类似Context角色
             * GatewayFilterChain: 过滤器链
             * Mono: Reactor核心类, 数据流发布者, Mono最多只触发⼀个事件, 所以可以把
             Mono 用于在异步任务完成时发出通知.
             * Mono.fromRunnable: 创建⼀个包含Runnable元素的数据流.类似与创建了一个线程
             */
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                log.info("[Pre] Filter Request:"+config.getName());
                return chain.filter(exchange).then(Mono.fromRunnable(()-> log.info("[Post] Response Filter")));//执行请求
            }
        };
    }
}

代码说明:

  • 自定义过滤器类名统一以GatewayFilterFactory结尾,因为在默认情况下,过滤器的name会采用该定义类的前缀,这里的name=Custom(yml配置中使用).
  • apply方法中,同时包含了Pre和Postman过滤,then方法中是请求执行结束之后处理的.
  • CustomConfig是一个配置类,该类只有一个属性name,和yml的配置对应.
  • 该类需要交给Spring进行管理,所以需要加@Comopent注解.
  • getOrder表示该过滤器的优先级.
配置过滤器
spring:
  cloud:
    gateway:
      metrics:
        enabled: true
      routes:
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/product/**
          filters:
            - name: Custom
              args:
                name: custom filter

2.5.2 自定义GlobalFilter

GlobalFilter的实现比较简单,它不需要额外的配置,只需要实现GlobalFilter接口,自动会过滤掉所有的Filter.

自定义GlobalFilter
@Component
@Slf4j
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("[Pre] CustomGlobalFilter enter...");
        return chain.filter(exchange).then(Mono.fromRunnable(()-> log.info("[Post] CustomGlobalFilter return...")));//执行请求
    }
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

回顾2024,展望2025

项目 LMD performance phase2 今年修修补补&#xff0c;设计和做了很多item&#xff0c;有时候自己都数不清做了什么大大小小的item&#xff0c;但是for LMD performance phase2的go-live确实是最大也是最难的了&#xff0c;无论什么系统&#xff0c;只要用的人多了&#xff…

旅游风景的代码项目

敦煌莫高窟&#xff1a;用代码打开千年艺术的大门 ——一个零基础也能看懂的神奇项目 前言&#xff1a;当古老艺术遇上现代代码 想象一下&#xff0c;你坐在电脑前&#xff0c;指尖轻轻一点&#xff0c;就能穿越到敦煌莫高窟——看飞天的衣袂飘飘、听千年的驼铃声声。这不是科…

解决lombok注解失效

问题描述 当出现使用lombok的注解, 但是找不到符号, 或者使用Getter注解却获取不到属性值 就像下面这样 原因: 新版本lombok自动引入了一个插件, 将下面这串代码删除后, 刷新并清除缓存即可解决

leetcode hot 100 搜索二维矩阵II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,2…

CentOS7安装使用containerd

一&#xff0c;安装 1.1、安装containerd 下载 https://github.com/containerd/containerd/releases/download/v1.7.24/cri-containerd-cni-1.7.24-linux-amd64.tar.gz wget https://github.com/containerd/containerd/releases/download/v1.7.24/cri-containerd-cni-1.7.24-…

easyexcel读取写入excel easyexceldemo

1.新建springboot项目 2.添加pom依赖 <name>excel</name> <description>excelspringboot例子</description><parent> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId&…

2025数学建模美赛|F题成品论文

国家安全政策与网络安全 摘要 随着互联网技术的迅猛发展&#xff0c;网络犯罪问题已成为全球网络安全中的重要研究课题&#xff0c;且网络犯罪的形式和影响日益复杂和严重。本文针对网络犯罪中的问题&#xff0c;基于多元回归分析和差异中的差异&#xff08;DiD&#xff09;思…

QT QTableWidget控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例,包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizontalSpacer)、…

SpringBoot--基本使用(配置、整合SpringMVC、Druid、Mybatis、基础特性)

这里写目录标题 一.介绍1.为什么依赖不需要写版本&#xff1f;2.启动器(Starter)是何方神圣&#xff1f;3.SpringBootApplication注解的功效&#xff1f;4.启动源码5.如何学好SpringBoot 二.SpringBoot3配置文件2.1属性配置文件使用2.2 YAML配置文件使用2.3 YAML配置文件使用2.…

QT TLS initialization failed

qt使用QNetworkAccessManager下载文件&#xff08;给出的链接可以在浏览器里面下载文件&#xff09;&#xff0c;下载失败&#xff0c; 提示“TLS initialization failed”通常是由于Qt在使用HTTPS进行文件下载时&#xff0c;未能正确初始化TLS&#xff08;安全传输层协议&…

WebODM之python实现

1、安装webodm_slam 主要是了解API文档,查看之前的文章 安装WebODM_slate 2、安装webodm 查看之前的文章 Win10安装WebODM和操作全流程 3、python脚本 项目案例 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of…

GitLab配置免密登录和常用命令

SSH 免密登录 Windows免密登录 删除现有Key 访问目录&#xff1a;C:\Users\Administrator\ .ssh&#xff0c;删除公钥&#xff1a;id_rsa.pub &#xff0c;私钥&#xff1a;id_rsa 2.生成.ssh 秘钥 运行命令生成.ssh 秘钥目录&#xff08; ssh-keygen -t rsa -C xxxxxx126.…

金融级分布式数据库如何优化?PawSQL发布OceanBase专项调优指南

前言 OceanBase数据库作为国产自主可控的分布式数据库&#xff0c;在金融、电商、政务等领域得到广泛应用&#xff0c;优化OceanBase数据库的查询性能变得愈发重要。PawSQL为OceanBase数据库提供了全方位的SQL性能优化支持&#xff0c;助力用户充分发挥OceanBase数据库的性能潜…

CentOS7非root用户离线安装Docker及常见问题总结、各种操作系统docker桌面程序下载地址

环境说明 1、安装用户有sudo权限 2、本文讲docker组件安装&#xff0c;不是桌面程序安装 3、本文讲离线安装&#xff0c;不是在线安装 4、目标机器是内网机器&#xff0c;与外部网络不连通 下载 1、下载离线安装包&#xff0c;并上传到$HOME/basic-tool 目录 下载地址&am…

嵌入式产品级-超小尺寸热成像相机(从0到1 硬件-软件-外壳)

Thermal_Imaging_Camera This is a small thermal imaging camera that includes everything from hardware and software. 小尺寸热成像相机-Pico-LVGL-RTOS 基于RP2040 Pico主控与RTOS&#xff0c;榨干双核性能实现LVGL和成图任务并行。ST7789驱动240280屏&#xff0c;CST8…

springfox-swagger-ui 3.0.0 配置

在3.0中&#xff0c;访问地址URL变了。 http://地址:端口/项目名/swagger-ui/ SpringBoot maven项目引入 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>3.0.0</version> </…

【0x03】HCI_Connection_Complete事件详解

目录 一、事件概述 二、事件格式及参数详解 2.1. HCI_Connection_Complete事件格式 2.2. 事件参数 2.2.1. Status 2.2.2. Connection_Handle 2.2.3. BD_ADDR 2.2.4. Link_Type 2.2.5. Encryption_Enabled 三、事件处理流程 3.1. 事件触发 3.2. 事件接收与解析 3.…

PCI 总线学习笔记(三)

PCI 总线学习系列&#xff0c;参考自 技术大牛博客&#xff1a; PCIe 扫盲系列博文连载目录篇 书籍&#xff1a;王齐老师的《PCI Express 体系结构导读》 下面的文章中加入了自己的一些理解和实际使用中遇到的一些场景&#xff0c;供日后查询和回忆使用 阅读本篇文章前&#x…

麒麟操作系统基础知识保姆级教程(二十一)进入单用户模式

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 在咱们运维工作中&#xff0c;服务器的密码长度&#xff0c;密码复杂度&#xff0c;修改时间&#xff0c;超时时间&#xff0c;用户权限管理&#xff0c;root直接远程连接&#xff0c;普通用户su到r…

ARM64平台Flutter环境搭建

ARM64平台Flutter环境搭建 Flutter简介问题背景搭建步骤1. 安装ARM64 Android Studio2. 安装Oracle的JDK3. 安装 Dart和 Flutter 开发插件4. 安装 Android SDK5. 安装 Flutter SDK6. 同意 Android 条款7. 运行 Flutter 示例项目8. 修正 aapt2 报错9. 修正 CMake 报错10. 修正 N…