Java之SpringCloud Alibaba【七】【Spring Cloud微服务网关Gateway组件】
一、网关简介
大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去用。

这样的架构,会存在着诸多的问题:
- 每个业务都会需要鉴权、限流、权限校验、跨域等逻辑,如果每个业务都各自为战。自己造轮子实现一遍,会很蛋疼,完全可以抽出来,放到一个统一的地方去做。
- 如果业务量比较简单的话,这种方式前期不会有什么问题,但随着业务越来越复杂,比如淘宝、亚马逊打开一个页面可能会涉及到数百个微服务协同工作,如果每一个微辰务都分配一个域名的话,一方面客户端代码会很难维护,涉及到数百个域名,另一方面是连接数的瓶颈想象一下你打开一个APP,通过抓包发现涉及到了数百个远程调用,这在移动端下会显得非常低效。
- 后期如果需要对微服务进行重构的话,也会变的非常麻烦,需要客户端配合你一起进行改造,比如商品服务,随着业务变的越来越复杂,后期需要进行拆分成多个微服务这个时候对外提供的服务也需要拆分成多个,同时需要客户端配合你进行改造,非常蛋疼。
上面的这些问题可以借助API网关来解决。

所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户说提供统一服务,一些与业务本身功能天关的公共逻辑可以在这里实现。诸如认证、鉴权、监控、路由转发等等,添加上API网关之后,系统的架构图变成了如下所示:


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

Spring Cloud Gateway 功能特征
- 基于Spring Framework 5, Project Reactor和 Spring Boot 2.0进行构建;
- 动态路由:能够匹配任何请求属性;
- 支持路径重写;
- 集成 Spring Cloud 服务发现功能(Nacos、Eruka) ;
- 可集成流控降级功能(Sentinel、Hystrix) ;
- 可以对路由指定易于编写的Predicate(断言)和Filter (过滤器);
2、核心概念
-
路由(route)
路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL和配置的路由匹配。 -
断言(predicates)
Java3中的断言函数,SpringCloud Gateway中的断言函数类型是Sping5.0框架中的SeverieExctange。断言函数允许开发者去定义匹酷t request中的任何信息,比加如请求头和参数等。 -
过滤器(Filter)
SpringCloud Gateway中的filter分为Gateway Filler和Global Filter。Filter可以对请求和响应进行处理
3、工作原理
Spring Cloud Gateway的工作原理跟Zuul的差不多,最大的区别就是Gateway的Filter只有pre和post 两种。

客户端向Spring Cloud Gateway发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关Web处理程序,此时处理程序运行特定的请求过滤器链。过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的前后执行逻辑。所有pre过滤器逻辑先执行,然后执行代理请求;代理请求完成后,执行post过滤器逻辑。
二、Spring Cloud Gateway快速开始
1、环境搭建【基本环境搭建-实现路由】
注意:会和spring-webmvc的依赖冲突,需要排除spring-webmvc




<dependencies><!--gateway的依赖 springcloud 开发--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency></dependencies>


设置配置文件

server:port: 8088
spring:application:name: api-gateway
# gateway的配置cloud:gateway:routes:- id: order_route #路由的唯一标识,路由到orderuri: http://localhost:8020 #需要转发的地址#断言规则 用于路由规则的匹配predicates:- Path=//# http://localhost:8088/order-serve/order/add 路由到↓# http://localhost:8020/order-serve/order/addfilters:- StripPrefix=1 # 转发之前,去掉第一次的路径# http://localhost:8020/order/add#- id: stock_route

访问:http://localhost:8088/order-serve/order/add

2、集成Nacos
<!-- nacos服务注册与发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>

server:port: 8088
spring:application:name: api-gateway
# gateway的配置cloud:gateway:routes:- id: order_route #路由的唯一标识,路由到orderuri: lb://order-service # 需要转发的地址 lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略 order-service服务名#断言规则 用于路由规则的匹配predicates:- Path=/order-serve/**# http://localhost:8088/order-serve/order/add 路由到↓# http://localhost:8020/order-serve/order/addfilters:- StripPrefix=1 # 转发之前,去掉第一次的路径# http://localhost:8020/order/add#- id: stock_route# 配置Nacosnacos:discovery:server-addr: 127.0.0.1:8848username: nacospassword: nacos

重新运行并访问:
http://localhost:8088/order-service/order/add

设置约定集成nacos

server:port: 8088
spring:application:name: api-gatewaycloud:# gateway的配置gateway:discovery:locator:enabled: true #是否启动自动识别nacos服务#配置Nacosnacos:discovery:server-addr: 127.0.0.1:8848username: nacospassword: nacos
重新启动项目
访问服务名对应的地址:http://localhost:8088/order-service/order/add

重新启动项目
访问:http://localhost:8088/order/add

调整时间

重新运行项目

http://localhost:8088/order/add

3、路由断言工厂(Route Predicate Factories)配置
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
作用:当请求gateway的时候, 使用断言对请求进行匹配, 如果匹配成功就路由转发,如果匹配失败就返回404
类型:内置,自定义
SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配。具体如下:
- 基于Datetime类型的断工厂
此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory:接收一个日期参数, 判断请求日期是否晚于指定日期
BeforeRoutePredicateFactory:接收- 个日期参数,判断请求日期是否早于指定日期
BetweenRoutePredicateFactory:接收两个日期参数,判断请求日期是否在指定时间段内
- After=2023-10-19T09:07:00.660+08:00[Asia/Shanghai]

- 基于远程地址的断言工厂
RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址段中
- RemoteAddr=192.168.1.1/24
- 基于Cookie的断言工厂
CookieRoutePredicateFactory:接收两个参数, cookie 名字和一个正则表达式。判断请求cookie是否具有给定名称且值与正则表达式匹配。
-Cookie=chocolate, ch.
- 基于Header的断言工厂
HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。判断请求Header是否具有给定名称且值与正则表达式匹配。
- Header=X-Request-Id, \d+

重新启动项目
利用API工具发送请求

把Headers当中的请求参数取消重新发起请求,会报错

- 基于Host的断言工厂
HostRoutePredicateFactory:接收一个参数, 主机名模式。判断请求的Host是否满足匹配规则。
-Host=**.testhost.org
- 基于Method请求方法的断言工厂
MethodRoutePredicateFactory:接收一个参数, 判断请求类型是否跟指定的类型匹配。

重新启动测试
通过GET发送请求

通过POST发起请求

- 基于Query请求参数的断言工厂

设置必须传递参数为name的参数
- Query=name
重新启动发起请求,没有设置name参数报错

设置name参数

设置指定参数

- Query=name,xushu|zhuge
设置name的参数只能是xushu或者zhuge否则断言失败
发送请求报错

将参数改为xushu请求成功,改为zhuge也请求成功

- 基于路由权重的断言工厂
WeightRoutePredicateFactory:接收-个[组名 权重],然后对于同-一个组内的路由按照权重转发
routes:-id: weight_ route1uri: host1predicates:-Path=/ product/**-Weight=group3,1-id: weight_ route2uri: host2predicates:- Path=/ product/**-Weight= group3, 9
4、自定义路由断言工厂
自定义路由断言工厂需要继承AbstractRoutePredicateFactory类,重写apply方法的逻辑。
在apply方法中可以通过exchange. getRequest()倒ServerHttpRequest对象,从而可以获取到请求的参数、请求方式、请求头等信息。
1、必须是Spring组件bean
2、类必须加上RoutePredicateFactory作为结尾
3、必须继承AbstractRoutePredicateFactory
4、必须声明静态的内部类 声明属性来接受配置文件当中配置的断言信息
5、需要结合shortcutFieldOrder进行绑定
6、通过apply方法进行逻辑判断 true 就是匹配成功 false就是匹配失败
注意:命名需要以RoutePredicateFactory结尾


@Component
public class CheckAuthRoutePredicateFactoryextends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {public CheckAuthRoutePredicateFactory() {super(CheckAuthRoutePredicateFactory.Config.class);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("name");}@Overridepublic Predicate<ServerWebExchange> apply(CheckAuthRoutePredicateFactory.Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {if(config.getName().equals("xushu")){return true;}return false;}};}// 用于接收配置文件中 断言的信息@Validatedpublic static class Config {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}}

重新启动项目

访问:http://localhost:8088/order/add

修改对应的断言名称

查询启动
http://localhost:8088/order/add

5、过滤器工厂( GatewayFilter Factories)配置

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayilter-factories


5.1、添加请求头参数

filters:- AddRequestHeader=X-Request-color,red

@RequestMapping("/header")public String header(@RequestHeader("X-Request-color") String color){return color;}

重新启动两个项目
http://localhost:8088/order/header

5.2、添加请求参数

- AddRequestParameter=color,blue

@RequestMapping("/parameter")public String parameter(@RequestParam("color") String color){return color;}
http://localhost:8088/order/parameter

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

servlet:context-path: /mall-order

- PrefixPath=/mall-order #添加前缀对应微服务需要配置context-path
重新启动两个项目

访问:http://localhost:8088/order/add

现在访问:http://localhost:8020/mall-order/order/add

然而访问8082必须携带前缀
http://localhost:8020/mall-order/order/add

5.4、配置重定向

- RedirectTo=302, https://www.baidu.com

访问:http://localhost:8088/order/add
重定向到了百度

5.5、自定义状态码

- SetStatus= 404

访问:http://localhost:8088/order/add
虽然访问成功了,但是返回的状态码为404

6、自定义过滤器工厂
继承AbstractNameValueGatewayFilterFactory且我们的自定义名称必须要以GatewayFilterFactory结尾并交给spring管理。
创建CheckAuthGatewayFilterFactory

/****/
@Component
public class CheckAuthGatewayFilterFactoryextends AbstractGatewayFilterFactory<CheckAuthGatewayFilterFactory.Config> {public CheckAuthGatewayFilterFactory() {super(Config.class);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("value");}@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String name=exchange.getRequest().getQueryParams().getFirst("name");if(StringUtils.isNotBlank(name)){if(config.getValue().equals(name)){return chain.filter(exchange);}else {// 返回404exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);return exchange.getResponse().setComplete();}}// 正常请求return chain.filter(exchange);}};}public static class Config {private String value;public String getValue() {return value;}public void setValue(String value) {this.value = value;}}}

- CheckAuth=xushu
7、全局过滤器(Global Filters)

局部过滤器和全局过滤器的区别
局部:针对某个路由,需要在路由中进行配置
全局:针对所有路由请求,一旦定义就会投入使用
GlobalFilter接口和GatewayFilter有一样的接口定义, 只不过,GlobalFilter 会作用于所有路由。



@Component
public class LogFilter implements GlobalFilter {Logger log= LoggerFactory.getLogger(this.getClass());@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info(exchange.getRequest().getPath().value());return chain.filter(exchange);}
}
重新启动:http://localhost:8088/order/add?name=xushu


8、Reactor Netty访问日志
要启用Reactor Netty访问日志,请设置
-Dreactor.netty.http.server.accessLogEnabled=true



它必须是Java系统属性,而不是Spring Boot属性。
您可以将日志记录系统配置为具有单独的访问日志文件。以下示例创建一个Logback配置:
<appender name=" accessLog" class="ch.qos.logback.core.FileAppender"><file>access_log.log</file><encoder><pattern>%msg%n</pattern></encoder>
</appender><appender name=" async" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="accessLog" />
</appender><logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false"><appender-ref ref=" async"/>
</logger>
8.1、Gateway跨域配置(CORS Configuration)
通过ym|配置的方式
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration

globalcors:cors-configurations:'[/**]': # 允许跨域访问的资源allowedOrigins: "*" #跨域允许的来源 例如:www.smsm.comallowedMethods:- GET- POST- PUT
模拟跨域请求,设置发起请求的页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body><div ><table border="1"><thead><tr><th>id</th><th>username</th><th>age</th></tr></thead><tbody id="userlist"></tbody></table></div><input type="button" value="用户列表" onclick="getData()"><script>function getData() {$.get('http://localhost:8088/order/add',function(data){alert(data)});}</script>
</body>
</html>

访问网页



allowedOrigins: "localhost:8088" #跨域允许的来源 例如:www.smsm.com

再次访问访问网页(抛出跨域异常)

设置*运行所有的来源访问

Spring自带的跨域方式



@Configuration
public class CorsConfig {@Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();config.addAllowedMethod("*"); //允许运行methodconfig.addAllowedOrigin("*"); //允许的来源config.addAllowedHeader("*"); //允许的请求头参数// 允许访问的资源UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration("/**",config);return new CorsWebFilter(source);}
}

相关文章:
Java之SpringCloud Alibaba【七】【Spring Cloud微服务网关Gateway组件】
一、网关简介 大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去用。 这样的架构,会存在着诸多…...
探讨jdk源码中的二分查找算法返回值巧妙之处
文章目录 1.什么是二分查找算法1.1 简介1.2 实现思路 2.二分查找的示例3.jdk 中的 Arrays.binarySearch()4.jdk 中核心二分查找方法解析4.1 为什么 low 是插入点4.2 为什么要进行取反:-(low 1)4.3 为什么不直接返回 插入点 low 的相反数&…...
深度学习实战:基于TensorFlow与OpenCV的手语识别系统
文章目录 写在前面基于TensorFlow与OpenCV的手语识别系统安装环境一、导入工具库二、导入数据集三、数据预处理四、训练模型基于CNN基于LeNet5基于ResNet50 五、模型预测基于OpenCV 写在后面 写在前面 本期内容:基于TensorFlow与OpenCV的手语识别系统 实验环境&…...
学习整理nginx常用屏蔽规则,让网站更安全
学习整理nginx常用屏蔽规则,让网站更安全 注意一、防止文件被下载二、屏蔽非常见蜘蛛(爬虫)三、禁止某个目录执行脚本四、屏蔽某个IP或IP段 注意 在开始之前,希望您已经熟悉的Nginx常用命令(如停止,重启等…...
四十一、【进阶】索引使用SQL提示
1、SQL提示使用情景 在使用MySQL时,当一个字段参在于多个索引中时,默认情况下,MySQL会自动选择一个索引,但我们可以指定索引吗?可以忽略某一种索引吗? 答案是可以的。 前提:profession字段已经…...
AI智能分析网关高空抛物算法如何实时检测高楼外立面剥落?
高楼外立面剥落是一种十分危险的行为,会造成严重的人身伤害和财产损失。TSINGSEE青犀智能分析网关利用高楼外立面剥落的信息,结合高空抛物算法来进行处理就可很好解决此问题。 1. 数据收集 首先,需要收集关于高楼外立面剥落的数据。这可以通…...
微信小程序 - 页面继承(非完美解决方案)
微信小程序 - 面页继承(非完美解决方案) 废话思路首页 indexindex.jsindex.jsonindex.wxml 父页面 page-basepage-base.jspage-base.wxml 子页面 page-apage-a.jspage-a.wxml 子页面 page-bpage-b.jspage-b.wxml 其它app.jsapp.jsonapp.wxss 参考资料 废…...
智能配件管理系统有什么用?企业如何实现管理数字化转型?
在当今高度信息化的时代,企业运营的各个环节都离不开准确及时的数据支持。特别是在制造业中,生产数据的记录和管理对于提高生产效率、降低成本、优化资源配置等方面具有至关重要的作用。然而,许多企业仍在采用纸质流转卡来记录生产数据&#…...
@SuppressWarnings注解使用说明
在Java编程中,我们常常会遇到一些警告(warnings),这些警告通常是对某些潜在问题的提示,虽然这些问题可能不会立即影响程序的运行,但可能会在将来引发问题。为了消除这些警告,我们可以使用Suppre…...
算法从入门到入土cpp版
1. 排序 1. 快速排序 # include<iostream> using namespace std;const int N 100010;int q[N];void quick_sort(int q[], int l, int r) {if(l>r) return;int il-1,jr1,tempq[l];while(i<j){do i;while(q[i]<temp);do j--;while(q[j]>temp);if(i<j)swa…...
没有PDF密码,如何解密文件?
PDF文件有两种密码,一个打开密码、一个限制编辑密码,因为PDF文件设置了密码,那么打开、编辑PDF文件就会受到限制。想要解密,我们需要输入正确的密码,但是有时候我们可能会出现忘记密码的情况,或者网上下载P…...
Sqlyog 无法连接 8 版本的mysql caching_sha2_password could not be loaded
Sqlyog 无法连接 8 版本的mysql caching_sha2_password could not be loaded 1.问题背景 近期系统对Mysql 版本进行了升级,由原来的 5.7升至 8版本,在现场使用Sqlyog 作为数据库连接软件时,发现连接失败。 2.问题现象 使用Sqlyog配置完连…...
学习笔记三十三:准入控制
ResourceQuota准入控制器 ResourceQuota准入控制器限制cpu、内存、pod、deployment数量限制存储空间大小 LimitRanger准入控制器在limit名称空间创建pod,不指定资源,看看是否会被limitrange规则自动附加其资源限制创建pod,指定cpu请求是100m&…...
Unix/Linux C语言 获取控制台窗口尺寸
在Unix/Linux控制台编程,为了能输出好看一些,需要知道窗口宽度,当然使用支持很宽的窗口的终端也是个办法,但是实在没有很宽的终端怎么办呢,还是要从程序上想办法的。 判断控制台窗口宽度需要两个函数: isa…...
界面控件DevExpress WinForms Gauge组件 - 实现更高级别数据可视化
DevExpress WinForms控件包含了超过150个随时可用的仪表盘预设,包括圆形,数字,线性和状态指示器等,来帮助用户实现更高级的数据可视化。 DevExpress WinForms有180组件和UI库,能为Windows Forms平台创建具有影响力的业…...
vivo 自研蓝河操作系统 BlueOS 发布:支持大模型、BlueXlink 协议实现万物互联
大家好,我是 Lorin , 2023 年 11 月 1 日,在今天的 2023 年 vivo 开发者大会上,vivo 自主研发的蓝河操作系统(BlueOS)正式亮相。这款操作系统被宣传为一款面向未来的智能操作系统,具备出色的支持能力&#…...
opencv复习(很乱)
2-高斯与中值滤波_哔哩哔哩_bilibili 1、均值滤波 2、高斯滤波 3、中值滤波 4、腐蚀操作 卷积核不都是255就腐蚀掉 5、膨胀操作 6、开运算 先腐蚀再膨胀 7、闭运算 先膨胀再腐蚀 8、礼帽 原始数据-开运算结果 9、黑帽 闭运算结果-原始数据 10、Sobel算子 左-右&#x…...
于璠访谈录 | AI 框架应该和而不同?
点击以下链接收听本期 “大咖访谈” 播客,与大咖面对面: 大咖访谈链接:于璠 | AI 框架应该和而不同? 刘天栋:访谈主持,开源雨林社区顾问、开源社联合创始人、ASF member 于璠:访谈嘉宾…...
基于Springboot+MYSQL+Maven实现的宠物医院管理系统(源码+数据库+运行指导文档+项目运行指导视频)
一、项目简介 本项目是一套基于springboot框架实现的宠物医院管理系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单…...
【数据结构二叉树】先序层序建立、递归非递归遍历层序遍历、树高、镜面、对称、子树、合并、目标路径、带权路径和等等
二叉树 文章目录 二叉树1. 二叉树的建立(递归创建,结构体指针形式)1.1. 先序建立1.2. 层序建立 2. 递归遍历(结构体指针)2.1. 先序遍历2.2. 中序遍历2.3. 后序遍历 3. 非递归遍历(结构体指针)3.1. 层次遍历3.2. 后序遍历(非递归) 4. 求树的高…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
