spring cloud alibaba-Geteway详解

news2025/5/22 18:15:13

spring cloud alibaba-Gateway详解

Gateway介绍

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

Gateway功能

  1. 统一入口
    • 微服务架构中,多个服务通常部署在不同的地址和端口上。网关作为统一的入口,将所有服务的请求集中管理,客户端只需要与网关交互,而不需要直接与各个微服务通信。
    • 这样可以简化客户端的逻辑,同时提高系统的安全性。
  2. 请求路由
    • 根据请求的特征(如路径、方法、参数等)将请求转发到对应的后端服务。
    • 路由规则可以动态配置,方便调整服务的访问路径。
  3. 负载均衡
    • 当后端服务有多个实例时,网关可以根据一定的策略(如轮询、随机、权重等)将请求分发到不同的实例,提高系统的可用性和性能。
  4. 流量控制
    • 限制请求的流量,防止后端服务被过多的请求压垮。
    • 常见的流量控制算法包括令牌桶算法、滑动窗口算法等。
  5. 身份认证
    • 对请求进行身份验证,确保只有合法的用户才能访问后端服务。
    • 常见的身份验证方式包括基于令牌(如 JWT)、基于用户名和密码等。
  6. 协议转换
    • 将一种协议的请求转换为另一种协议的请求,例如将 HTTP 请求转换为 gRPC 请求。
    • 这样可以实现不同协议之间的通信,提高系统的灵活性。
  7. 系统监控
    • 监控网关的运行状态,包括请求量、响应时间、错误率等指标。
    • 通过监控可以及时发现系统的问题,提高系统的可靠性。
  8. 安全防护
    • 防止恶意攻击,如 SQL 注入、XSS 攻击、CSRF 攻击等。
    • 通过安全策略(如防火墙规则、WAF 等)保护系统免受攻击。

创建网关

创建一个新项目

  1. 导入依赖
        <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>
  1. 编写启动类
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);
    }
}
  1. 配置application.yml文件
spring:
  application:
    name: gateway

  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
  profiles:
    include: route
server:
  port: 80

  1. 配置路由规则 application-route.yml
spring:
  cloud:
    gateway:
      routes:
        - id: order-route
          uri: lb://service-order
          predicates:
            - Path=/api/order/**
        - id: product-route
          uri: lb://service-product
          predicates:
            - Path=/api/product/**
@RequestMapping("/api/order/")
@RestController
public class OrderController {

    @GetMapping("/readDb")
    public String readDb(){
        return "readDb";
    }

}

测试:说明是能访问到的
在这里插入图片描述

  1. 进入Nacos
    在这里插入图片描述

断言

断言工厂
名称参数(个数/类型)作用
After1/datetime在指定时间之后
Before1/datetime在指定时间之前
Between2/datetime在指定时间区间内
Cookie2/string, regexp包含cookie名且必须匹配指定值
Header2/string, regexp包含请求头且必须匹配指定值
HostN/string请求host必须是指定枚举值
MethodN/string请求方式必须是指定枚举值
Path2/List, bool请求路径满足规则,是否匹配最后的/
Query2/string, regexp包含指定请求参数
RemoteAddr1/List请求来源于指定网络域(CIDR写法)
Weight2/string, int按指定权重负载均衡
XForwarded1/List从X-Forwarded-For请求头中解析请求来源,并判断是否来源于指定网络域

例如:
predicates的意思就是断言
Cookie:路由断言工厂(名)
mycookie,mycookievalue:参数

spring:
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: https://example.org
          predicates:
            - Cookie=mycookie,mycookievalue

假如我们要转发到百度 我们在加上一些断言规则

spring:
 cloud:
   gateway:
     routes:
       - id: bing-route
         uri: https://cn.bing.com/
         predicates:
           - name: Path
             args:
               pattern: /search
           - name: Query
             args:
               param: q
               regexp: 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路由
     */
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {
            /**
             * 判断请求是否匹配VIP路由的逻辑。
             *
             * @param serverWebExchange 当前的请求上下文
             * @return 如果请求参数中存在指定参数且值匹配,则返回true,否则返回false
             */
            @Override
            public 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 返回字段顺序列表
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("param", "value");
    }

    /**
     * 配置类,用于存储路由断言的配置信息。
     */
    @Validated
    public static class Config {

        /**
         * 请求参数名,用于从请求中获取参数值。
         */
        @NotEmpty
        private String param;

        /**
         * 请求参数期望值,用于判断请求参数值是否匹配。
         */
        @NotEmpty
        private 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-route
          uri: https://cn.bing.com/
          predicates:
            - name: Path
              args:
                pattern: /search
            - name: Query
              args:
                param: q
                regexp: haha
            - name: Vip
              args:
                param: user
                value: xiaonie

在这里插入图片描述

我出现的错误

我在这里犯了一个大错误

java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name VipRoutePredicateFactory

我检查了好几遍代码都没问题 最后我发现我在这里把这个包放在了外面去了 所以他没有扫描到这个包 希望打架也注意一下

过滤器

路径重写

如果加上了路径重写那么微服务前面就不需要加上/api/模块名

spring:
  cloud:
    gateway:
      routes:
        - id: bing-route
          uri: https://cn.bing.com/
          predicates:
            - name: Path
              args:
                pattern: /search
            - name: Query
              args:
                param: q
                regexp: haha
            - name: Vip
              args:
                param: user
                value: xiaonie
        - id: order-route
          uri: lb://service-order
          predicates:
            - Path=/api/order/**
          filters:
            - RewritePath=/api/order/(?<segment>.*), /$\{segment}
          order: 1
        - id: product-route
          uri: lb://service-product
          predicates:
            - 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 {

    @Autowired
    private OrderService orderService;

    @Autowired
    private 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 {

    @Override
    public 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);
                }); //放行  10s



        return filter;
    }

    @Override
    public 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 {

    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return new GatewayFilter() {

            @Override
            public 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: '*'

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c#中添加visionpro控件(联合编程)

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

性能测试-mysql监控

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

游戏引擎学习第301天:使用精灵边界进行排序

回顾并为今天的内容做准备 昨天&#xff0c;我们解决了一些关于排序的问题&#xff0c;这对我们清理长期存在的Z轴排序问题很有帮助。这个问题我们一直想在开始常规游戏代码之前解决。虽然不确定是否完全解决了问题&#xff0c;但我们提出了一个看起来合理的排序标准。 有两点…

【AI生成PPT】使用ChatGPT+Overleaf自动生成学术论文PPT演示文稿

【AI生成PPT】使用ChatGPTOverleaf自动生成学术论文PPT演示文稿 文章摘要&#xff1a;使用ChatGPTBeamer自动生成学术论文PPT演示文稿​​Beamer​​是什么Overleaf编辑工具ChatGPT生成Beamer Latex代码论文获取prompt设计 生成结果 文章摘要&#xff1a; 本文介绍了一种高效利…

局部放大maya的视图HUD文字大小的方法

一、问题描述&#xff1a; 有网友问&#xff1a;有办法局部放大maya的字体吗比如hud中currenttime打开之后画面右下角有个frame 想放大一下能做到吗&#xff1f; 在 Maya 中&#xff0c;可以通过自定义 HUD&#xff08;Heads-Up Display&#xff09;元素的字体大小来局部放大特…

初识Linux · NAT 内网穿透 内网打洞 代理

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

STM32接收红外遥控器的遥控信号

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

Redis从入门到实战 - 高级篇(下)

一、Redis键值设计 1. 优雅的key结构 Redis的Key虽然可以自定义&#xff0c;但最好遵循下面几个最佳实践约定&#xff1a; 遵循基本格式&#xff1a;[业务名称]:[数据名]:[id]长度不超过44字节不包含特殊字符 例如&#xff1a;我们的登录业务&#xff0c;保存用户信息&…

GUI实验

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

量子计算 | 量子密码学的挑战和机遇

量子计算在密码学中的应用现主要体现在对现有加密算法的威胁上。最著名的例子是Shor算法&#xff0c;该算法能够在多项式时间内分解大整数&#xff0c;从而威胁到基于大数分解的加密算法&#xff0c;如RSA加密。此外&#xff0c;量子计算还可以加速某些类型的密码分析&#xff…

分享一些多模态文档解析思路

多模态文档解析思路小记 作者&#xff1a;Arlene 原文&#xff1a;https://zhuanlan.zhihu.com/p/1905635679293122466 多模态文档解析内容涉及&#xff1a;文本、表格和图片 解析思路v1 基于mineru框架对pdf文件进行初解析 其具备较完整的布局识别和内容识别&#xff0c;并将…

AI知识梳理——RAG、Agent、ReAct、LangChain、LangGraph、MCP、Function Calling、JSON-RPC

AI技术I AI技术II RAG &#x1f4cc; 高度凝练表达 RAG &#xff08;检索增强生成&#xff09;是一种结合信息检索与生成式人工智能的技术框架&#xff0c;旨在提升大型语言模型&#xff08;LLM&#xff09;的输出准确性和实用性。通过在生成响应前引入外部知识库的信息&#…

【实用教程】如何快速搭建一套私有的埋点系统?

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

深入解析 Uniswap:自动做市商模型的数学推导与智能合约架构

目录 1. 自动做市商&#xff08;AMM&#xff09;模型的数学推导1.1 恒定乘积公式推导1.2 价格影响与滑点 2. Uniswap 智能合约架构解析2.1 核心合约&#xff08;Core&#xff09;2.1.1 工厂合约&#xff08;Factory&#xff09;2.1.2 交易对合约&#xff08;Pair&#xff09; 2…

React 19版本refs也支持清理函数了。

文章目录 前言一、refs 支持清理函数二、案例演示1.useEffect写法2.React 19改进 的ref写法 总结 前言 React 19版本发布了ref支持清理函数了&#xff0c;这样就可以达到useEffect一样的效果了。为啥需要清理函数呢&#xff0c;这是因为节约内存。 清理事件监听&#xff08;避…

阿尔泰科技助力电厂——520为爱发电!

当城市的霓虹在暮色中亮起&#xff0c;当千万个家庭在温暖中共享天伦&#xff0c;总有一群默默的 "光明守护者" 在幕后坚守 —— 它们是为城市输送能量的电厂&#xff0c;更是以科技赋能电力行业的阿尔泰科技。值此 520 爱意满满的日子&#xff0c;阿尔泰科技用硬核技…

C#语法篇 :基类子类转换,成员变化情况

在C#中&#xff0c;会有从子类对象到基类对象的转换&#xff0c;这属于C#中的向上扩容&#xff0c;一般可以默认转换。 方法的转换 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ex3._4 …

【漫话机器学习系列】264.内距(又称四分位差)Interquartile Range

深入理解内距&#xff08;Interquartile Range&#xff0c;IQR&#xff09;——数据分析中的异常值利器 在日常的数据分析中&#xff0c;我们经常需要识别和处理异常值&#xff08;Outliers&#xff09;&#xff0c;而内距&#xff08;Interquartile Range&#xff0c;简称 IQR…

海外盲盒系统开发:重构全球消费体验的科技引擎

当盲盒文化席卷全球&#xff0c;海外盲盒系统开发已成为重构消费体验的核心赛道。数据显示&#xff0c;2025年全球盲盒市场规模突破120亿&#xff0c;东南亚市场年增长率达4540。我们开发的海外盲盒系统&#xff0c;以技术创新为驱动&#xff0c;打造覆盖全链路的全球化解决方案…

高噪声下扩展边缘检测算子对检测边缘的影响

目录 一、常见的边缘检测算子 二、扩展边缘检测算子对检测边缘的影响 三、结论 一、常见的边缘检测算子 Sobel 算子: Prewitt算子;