spring cloud alibaba-Geteway详解
spring cloud alibaba-Gateway详解
Gateway介绍
在 Spring Cloud Alibaba 生态系统中,Gateway 是一个非常重要的组件,用于构建微服务架构中的网关服务。它基于 Spring Cloud Gateway 进行扩展和优化,提供了更强大的功能和更好的性能。
Gateway功能
- 统一入口
• 微服务架构中,多个服务通常部署在不同的地址和端口上。网关作为统一的入口,将所有服务的请求集中管理,客户端只需要与网关交互,而不需要直接与各个微服务通信。
• 这样可以简化客户端的逻辑,同时提高系统的安全性。 - 请求路由
• 根据请求的特征(如路径、方法、参数等)将请求转发到对应的后端服务。
• 路由规则可以动态配置,方便调整服务的访问路径。 - 负载均衡
• 当后端服务有多个实例时,网关可以根据一定的策略(如轮询、随机、权重等)将请求分发到不同的实例,提高系统的可用性和性能。 - 流量控制
• 限制请求的流量,防止后端服务被过多的请求压垮。
• 常见的流量控制算法包括令牌桶算法、滑动窗口算法等。 - 身份认证
• 对请求进行身份验证,确保只有合法的用户才能访问后端服务。
• 常见的身份验证方式包括基于令牌(如 JWT)、基于用户名和密码等。 - 协议转换
• 将一种协议的请求转换为另一种协议的请求,例如将 HTTP 请求转换为 gRPC 请求。
• 这样可以实现不同协议之间的通信,提高系统的灵活性。 - 系统监控
• 监控网关的运行状态,包括请求量、响应时间、错误率等指标。
• 通过监控可以及时发现系统的问题,提高系统的可靠性。 - 安全防护
• 防止恶意攻击,如 SQL 注入、XSS 攻击、CSRF 攻击等。
• 通过安全策略(如防火墙规则、WAF 等)保护系统免受攻击。
创建网关
创建一个新项目
- 导入依赖
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><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><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-gateway</artifactId></dependency></dependencies>
- 编写启动类
package com.nie.gateway;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplicationMain {public static void main(String[] args) {SpringApplication.run(GatewayApplicationMain.class,args);}
}
- 配置application.yml文件
spring:application:name: gatewaycloud:nacos:server-addr: 127.0.0.1:8848profiles:include: route
server:port: 80
- 配置路由规则 application-route.yml
spring:cloud:gateway:routes:- id: order-routeuri: lb://service-orderpredicates:- Path=/api/order/**- id: product-routeuri: lb://service-productpredicates:- Path=/api/product/**
@RequestMapping("/api/order/")
@RestController
public class OrderController {@GetMapping("/readDb")public String readDb(){return "readDb";}}
测试:说明是能访问到的
- 进入Nacos
断言
断言工厂
名称 | 参数(个数/类型) | 作用 |
---|---|---|
After | 1/datetime | 在指定时间之后 |
Before | 1/datetime | 在指定时间之前 |
Between | 2/datetime | 在指定时间区间内 |
Cookie | 2/string, regexp | 包含cookie名且必须匹配指定值 |
Header | 2/string, regexp | 包含请求头且必须匹配指定值 |
Host | N/string | 请求host必须是指定枚举值 |
Method | N/string | 请求方式必须是指定枚举值 |
Path | 2/List, bool | 请求路径满足规则,是否匹配最后的/ |
Query | 2/string, regexp | 包含指定请求参数 |
RemoteAddr | 1/List | 请求来源于指定网络域(CIDR写法) |
Weight | 2/string, int | 按指定权重负载均衡 |
XForwarded | 1/List | 从X-Forwarded-For请求头中解析请求来源,并判断是否来源于指定网络域 |
例如:
predicates的意思就是断言
Cookie:路由断言工厂(名)
mycookie,mycookievalue:参数
spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:- Cookie=mycookie,mycookievalue
假如我们要转发到百度 我们在加上一些断言规则
spring:cloud:gateway:routes:- id: bing-routeuri: https://cn.bing.com/predicates:- name: Pathargs:pattern: /search- name: Queryargs:param: qregexp: haha
这时候我们访问时必须为/serrch 必须带上参数 参数名为q 值必须为haha我们才能成功转发
如果值不等于haha 或者参数名不为q 那么会出现404找不到页面错误
自定义断言工厂
package com.nie.gateway.predicate;import jakarta.validation.constraints.NotEmpty;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;/*** 自定义的VIP路由断言工厂类,用于根据请求参数判断是否匹配VIP路由。* 继承自AbstractRoutePredicateFactory,实现了自定义路由断言逻辑。*/
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {/*** 构造函数,指定配置类为Config。*/public VipRoutePredicateFactory() {super(Config.class);}/*** 实现apply方法,根据Config中的配置生成路由断言逻辑。** @param config 配置对象,包含请求参数名和期望值* @return 返回一个Predicate<ServerWebExchange>,用于判断请求是否匹配VIP路由*/@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return new GatewayPredicate() {/*** 判断请求是否匹配VIP路由的逻辑。** @param serverWebExchange 当前的请求上下文* @return 如果请求参数中存在指定参数且值匹配,则返回true,否则返回false*/@Overridepublic boolean test(ServerWebExchange serverWebExchange) {ServerHttpRequest request = serverWebExchange.getRequest();// 获取请求参数中指定参数的第一个值String first = request.getQueryParams().getFirst(config.param);// 判断参数值是否存在且是否等于配置的期望值if (StringUtils.hasText(first) && first.equals(config.value)) {return true;}return false;}};}/*** 定义配置类的字段顺序,用于在配置文件中指定参数时的顺序。** @return 返回字段顺序列表*/@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("param", "value");}/*** 配置类,用于存储路由断言的配置信息。*/@Validatedpublic static class Config {/*** 请求参数名,用于从请求中获取参数值。*/@NotEmptyprivate String param;/*** 请求参数期望值,用于判断请求参数值是否匹配。*/@NotEmptyprivate String value;/*** 获取请求参数名。** @return 返回请求参数名*/public String getParam() {return param;}/*** 设置请求参数名。** @param param 请求参数名*/public void setParam(String param) {this.param = param;}/*** 获取请求参数期望值。** @return 返回请求参数期望值*/public String getValue() {return value;}/*** 设置请求参数期望值。** @param value 请求参数期望值*/public void setValue(String value) {this.value = value;}}
}
spring:cloud:gateway:routes:- id: bing-routeuri: https://cn.bing.com/predicates:- name: Pathargs:pattern: /search- name: Queryargs:param: qregexp: haha- name: Vipargs:param: uservalue: xiaonie
我出现的错误
我在这里犯了一个大错误
java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name VipRoutePredicateFactory
我检查了好几遍代码都没问题 最后我发现我在这里把这个包放在了外面去了 所以他没有扫描到这个包 希望打架也注意一下
过滤器
路径重写
如果加上了路径重写那么微服务前面就不需要加上/api/模块名
spring:cloud:gateway:routes:- id: bing-routeuri: https://cn.bing.com/predicates:- name: Pathargs:pattern: /search- name: Queryargs:param: qregexp: haha- name: Vipargs:param: uservalue: xiaonie- id: order-routeuri: lb://service-orderpredicates:- Path=/api/order/**filters:- RewritePath=/api/order/(?<segment>.*), /$\{segment}order: 1- id: product-routeuri: lb://service-productpredicates:- Path=/api/product/**filters:- RewritePath=/api/product/(?<segment>.*), /$\{segment}order: 2
package com.nie.order.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.nie.order.bean.Order;
import com.nie.order.properties.OrderProperties;
import com.nie.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class OrderController {@Autowiredprivate OrderService orderService;@Autowiredprivate OrderProperties orderProperties;@GetMapping("/readDb")public String readDb(){return "readDb";}@GetMapping("/seckill")@SentinelResource(value = "seckill-order", fallback = "seckillFallback")public Order seckill(@RequestParam("userId") Long userId,@RequestParam("productId") Long productId){Order order = orderService.createOrder(productId, userId);order.setId(Long.MAX_VALUE);return order;}public Order seckillFallback(Long userId, Long productId, Throwable exception){System.out.println("已经开始限制了");Order order = new Order();order.setId(productId);order.setUserId(userId);order.setAddress("异常信息:" + exception.getClass());return order;}@GetMapping("/config")public String config(){return "order.timeout = " + orderProperties.getTimeout()+ ", order.auto-confirm = " + orderProperties.getAutoConfirm()+"order.db="+orderProperties.getDb();}@GetMapping("/create")public Order createOrder(@RequestParam("userId") Long userId,@RequestParam("productId") Long productId){Order order = orderService.createOrder(productId,userId);return order;}
}
这样也就能访问 避免后期因为规划不周到 需要大量改前缀
filters:- RewritePath=/api/product/(?<segment>.*), /$\{segment}- AddResponseHeader=X-Response-Abcd, 123
如果我们加上AddResponseHeader=X-Response-Abcd, 123
那么在我们每次请求中他都会带上响应头 值为123
默认过滤器
default-filters:- AddResponseHeader=X-Response-Abcd, 123
用上面的例子的话我们就在每次请求中都带入了请求头 值为123
就不用在每个微服务上面都加了
全局Filters
package com.nie.gateway.filter;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Slf4j
@Component
public class RtGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();String uri = request.getURI().toString();long start = System.currentTimeMillis();log.info("请求【{}】开始: 时间: {}", uri, start);//=============以上是前置逻辑================Mono<Void> filter = chain.filter(exchange).doFinally((result)->{//=============以下是后置逻辑================long end = System.currentTimeMillis();log.info("请求【{}】结束: 时间: {}, 耗时: {}ms",uri,end,end-start);}); //放行 10sreturn filter;}@Overridepublic int getOrder() {return 0;}
}
自定义过滤器
filters:- RewritePath=/api/order/(?<segment>.*), /$\{segment}- OnceTooken=X-Response-Token, uuid
package com.nie.gateway.filter;import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.UUID;@Component
public class OnceTokenGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//每次响应之前,添加一个一次性令牌,支持 uuid, jwt等各种格式return chain.filter(exchange).then(Mono.fromRunnable(() -> {ServerHttpResponse response = exchange.getResponse();HttpHeaders headers = response.getHeaders();String value = config.getValue();if ("uuid".equalsIgnoreCase(value)) {value = UUID.randomUUID().toString();}if ("jwt".equalsIgnoreCase(value)) {value = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiIjoiMjQ4OTY3Nzg5IiwibmFtZSI6IkpvaG4gRG9lIiLCJleHAiOjE2NTM5MDk3OTksImlhdCI6MTY1MzkwOTc5OCwiZXhwIjoxNjUzOTA5NzkwLCJpc3MiOiJhdXRoIjoiLCJuYW1lIjoiYXV0aG9ycyIsImV4cCI6MTY1MzkwOTc5OCwianRpIjoiMjAyMyIsInR5cCI6IkpXVCJ9LCJpYXQiOjE2NTM5MDk3OTksImV4cCI6MTY1MzkwOTc5OCwiaXNzIjoiaHR0cHM6Ly9hdXRoLmF1dGhvcnMubmV0L3VzZXIiIsImF1dGhvcml0eSI6eyJpZGVudGl0eSI6eyJjbGllbnRzIjp7InVzZXJAZXhhbXBsZS5jb20iOnsiYWV0Ijp7InVzZXJAZXhhbXBsZS5jb20iOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyQGV4YW1wbGUiOnsiZXhhbXBsZSI6eyJ1c2VyGVyIjp7fSwicmV4cCI6eyJyIjoiLCJLCJsYW1vdW50aWVub3JhbCIsImZSI6eyJ1c2VyIjp7fX19LCJ30=\n";}headers.add(config.getName(), value);}));}};}}
全局跨域
这样配置application.yml之后
允许所有请求跨域 allowed-origin-patterns: ‘’
允许全部请求来源 允许所有的头 allowed-headers: '’
允许所有的请求方式 allowed-methods: ‘*’
spring:cloud:gateway:globalcors:cors-configurations:'[/**]':allowed-origin-patterns: '*'allowed-headers: '*'allowed-methods: '*'
相关文章:

spring cloud alibaba-Geteway详解
spring cloud alibaba-Gateway详解 Gateway介绍 在 Spring Cloud Alibaba 生态系统中,Gateway 是一个非常重要的组件,用于构建微服务架构中的网关服务。它基于 Spring Cloud Gateway 进行扩展和优化,提供了更强大的功能和更好的性能。 Gat…...

c#中添加visionpro控件(联合编程)
vs添加vp控件 创建窗体应用 右键选择项 点击确定 加载CogAcqfifoTool工具拍照 设置参数保存.vpp 保存为QuickBuild或者job, ToolBlock 加载保存的acq工具 实例化相机工具类 //引入命名空间 using Cognex.VisionPro; //实例化一个相机工具类 CogAcqFifoTool cogAcqFifoTool n…...

性能测试-mysql监控
mysql常用监控指标 慢查询sql 慢查询:指执行速度低于设置的阀值的sql语句 作用:帮助定位查询速度较慢的sql语句,方便更好的优化数据库系统的性能 开启mysql慢查询日志 参数说明: slow_query_log:慢查询日志开启状态【on…...

游戏引擎学习第301天:使用精灵边界进行排序
回顾并为今天的内容做准备 昨天,我们解决了一些关于排序的问题,这对我们清理长期存在的Z轴排序问题很有帮助。这个问题我们一直想在开始常规游戏代码之前解决。虽然不确定是否完全解决了问题,但我们提出了一个看起来合理的排序标准。 有两点…...
CSS attr() 函数详解
attr() 是 CSS 中的一个函数,用于获取 HTML 元素的属性值并在样式中使用。虽然功能强大,但它的应用有一些限制和注意事项。 基本语法 element::pseudo-element {property: attr(attribute-name); } 可用场景 1. 在伪元素的 content 属性中使用&#…...

【AI生成PPT】使用ChatGPT+Overleaf自动生成学术论文PPT演示文稿
【AI生成PPT】使用ChatGPTOverleaf自动生成学术论文PPT演示文稿 文章摘要:使用ChatGPTBeamer自动生成学术论文PPT演示文稿Beamer是什么Overleaf编辑工具ChatGPT生成Beamer Latex代码论文获取prompt设计 生成结果 文章摘要: 本文介绍了一种高效利…...
流复备机断档处理
文章目录 环境症状问题原因解决方案 环境 系统平台:UOS(海光),UOS (飞腾),UOS(鲲鹏),UOS(龙芯),UOS (申威),银河麒麟svs(X86_64&…...
Linux 安装 pytorch+cuda+gpu 大模型开发环境过程记录
Linux 安装 pytorchcudagpu 大模型开发环境过程记录 2025-05-17 本文可用于生产环境,用于大模型训练开发运行。 1. 确定 OS 架构 # cat /etc/os-release NAME"Ubuntu" VERSION"20.04.6 LTS (Focal Fossa)" # uname -m x86_642. 查看磁盘空间…...

局部放大maya的视图HUD文字大小的方法
一、问题描述: 有网友问:有办法局部放大maya的字体吗比如hud中currenttime打开之后画面右下角有个frame 想放大一下能做到吗? 在 Maya 中,可以通过自定义 HUD(Heads-Up Display)元素的字体大小来局部放大特…...
数学复习笔记 16
前言 例题真是经典。 background music 《青春不一样》 2.28 算一个行列式,算出来行列式不等于零,这表示矩阵式可逆的。但是这个算的秩是复合的,感觉没啥好办法了,我直接硬算了,之后再看解析积累好的方法。算矩阵…...

初识Linux · NAT 内网穿透 内网打洞 代理
目录 前言: 内网穿透和打洞 NAPT表 内网穿透 内网打洞 正向/反向代理 前言: 本文算是网络原理的最后一点补充,为什么说是补充呢,因为我们在前面第一次介绍NAT的时候详细介绍的是报文从子网到公网,却没有介绍报文…...

STM32接收红外遥控器的遥控信号
经过几天早晨的学习,终于把遥控器的红外信号给搞通了,特此记录一下;其实说白了,红外遥控就是高低电平的信号,用时间来区分是二进制的0还是1;然后把这些0或1,在组装成一个32位的数基本就算是完事…...

Redis从入门到实战 - 高级篇(下)
一、Redis键值设计 1. 优雅的key结构 Redis的Key虽然可以自定义,但最好遵循下面几个最佳实践约定: 遵循基本格式:[业务名称]:[数据名]:[id]长度不超过44字节不包含特殊字符 例如:我们的登录业务,保存用户信息&…...
NGINX常用功能—笔记
NGINX 是一款高性能的开源 Web 服务器和反向代理服务器,常用于处理高并发场景,其功能丰富且灵活。以下是 NGINX 的常用功能及详细说明: 一、静态资源服务器 功能说明:直接处理 HTML、CSS、JavaScript、图片、视频等静态文件请求&a…...
JVM 性能问题排查实战10连击
🗂️ 目录 前言:理论掌握只是起点,定位能力才是核心全局排查模型:三步法1️⃣Full GC 频繁触发:老年代压力过大2️⃣ OOM 爆炸:元空间泄漏 or 缓存未清理3️⃣ CPU 飙升却不是 GC:线程阻塞或热方…...
【jvm第8集】jvm调优工具(图形化工具)
文章目录 一、JVM 调优图形化工具分类二、JDK 自带工具JConsoleVisualVM 三、第三方工具MAT(Memory Analyzer Tool)JProfiler(商业工具)YourKit(商业工具) 四、APM工具全链路监控与智能运维(AIO…...
Python测试单例模式
单例模式的核心思想 单例模式确保一个类只有一个实例,并提供一个全局访问点。这在需要控制资源访问(如配置文件、数据库连接等)时非常有用。 一个简单的示例: import threading import timeclass Singleton:instance Nonelock…...
多技术栈 iOS 项目的性能调试实战:从 Flutter 到 Unity(含 KeyMob 工具实测)
多技术栈 iOS 项目的性能调试实战:从 Flutter 到 Unity 随着移动端开发日趋多元化,iOS 项目中纯 Objective-C/Swift 已不再是唯一选择。越来越多团队采用 Flutter、React Native、Unity、WebView 混合等方案构建 App。这种“技术栈混合”带来灵活性的同…...
STM32简易计算机设计
运用 A0上拉按钮和 A1 A2下拉按钮设计按键功能 加上独特的算法检测设计,先计算()内在计算乘除在计算加减的值在计算乘除优先级最后计算加减优先级 #include "stm32f10x.h" #include <stdio.h> #include <stdlib.h>…...

GUI实验
题目: 编程包含一个标签和一个按钮,单击按钮时,标签的内容在"你好"和"再见"之间切换。 分析: 导入所需的Java库:程序使用了 javax.swing 包中的一些类来创建图形用户界面。 创建一个 JFrame 对象…...

量子计算 | 量子密码学的挑战和机遇
量子计算在密码学中的应用现主要体现在对现有加密算法的威胁上。最著名的例子是Shor算法,该算法能够在多项式时间内分解大整数,从而威胁到基于大数分解的加密算法,如RSA加密。此外,量子计算还可以加速某些类型的密码分析ÿ…...
linux系统查看硬盘序列号
Linux系统查看硬盘信息指南 方法一:hdparm工具 sudo hdparm -i /dev/sda输出示例:在返回信息中查找"SerialNo"字段为序列号,"Model"字段为硬盘型号注意:必须使用root权限,普通用户需在命令前加s…...

分享一些多模态文档解析思路
多模态文档解析思路小记 作者:Arlene 原文:https://zhuanlan.zhihu.com/p/1905635679293122466 多模态文档解析内容涉及:文本、表格和图片 解析思路v1 基于mineru框架对pdf文件进行初解析 其具备较完整的布局识别和内容识别,并将…...
CSS 选择器入门
一、CSS 选择器基础:快速掌握核心概念 什么是选择器? CSS 选择器就像 “网页元素的遥控器”,用于定位 HTML 中的特定元素并应用样式。 /* 结构:选择器 { 属性: 值; } */ p { color: red; } /* 选择所有<p>元素,…...
【Django】Django DRF 中如何手动调用分页器返回分页数据(APIView,action场景)
📦 Django DRF 中如何手动调用分页器返回分页数据(APIView,action场景) 在使用 Django REST Framework(DRF)时,很多人习惯了用 GenericAPIView 或 ViewSet 自动帮我们处理分页。但在某些场景中…...

AI知识梳理——RAG、Agent、ReAct、LangChain、LangGraph、MCP、Function Calling、JSON-RPC
AI技术I AI技术II RAG 📌 高度凝练表达 RAG (检索增强生成)是一种结合信息检索与生成式人工智能的技术框架,旨在提升大型语言模型(LLM)的输出准确性和实用性。通过在生成响应前引入外部知识库的信息&#…...
Vue组件通信方式及最佳实践
1. Props / 自定义事件 (父子通信) 使用场景 父子组件直接数据传递 代码实现 <!-- Parent.vue --> <template><Child :message"parentMsg" update"handleUpdate" /> </template><script setup> import { ref } from vue…...

【实用教程】如何快速搭建一套私有的埋点系统?
这篇教程将基于开源项目-ClkLog,教大家快速搭建一套自有的埋点系统,从0开始完成数据采集、分析与展示,全流程掌控用户行为数据。 ClkLog是一款支持私有化部署的全开源用户行为数据采集与分析系统,兼容Web、App、小程序多端埋点&am…...

深入解析 Uniswap:自动做市商模型的数学推导与智能合约架构
目录 1. 自动做市商(AMM)模型的数学推导1.1 恒定乘积公式推导1.2 价格影响与滑点 2. Uniswap 智能合约架构解析2.1 核心合约(Core)2.1.1 工厂合约(Factory)2.1.2 交易对合约(Pair) 2…...
spring配置并使用rabbitmq
本篇博客默认你已经成功安装了rabbitmq。如未安装,可参照官网https://www.rabbitmq.com/docs/platforms,选择对应平台进行安装 一、虚拟主机 虚拟主机的概念: 虚拟主机不是指vm虚拟机,而是指一个通过逻辑进行资源隔离和分区的机…...