《Spring Cloud Gateway 快速入门:从路由到自定义 Filter 的完整教程》
1.网关介绍
在前面的学习中,我们通过Eureka和Nacos解决了辅助注册,使用Spring Cloud LoadBalance解决了负载均衡的问题,使用OpenFeign解决了远程调用的问题。
但是当前的所有微服务的接口都是直接对外暴露的,外部是可以直接访问的,为了保证对外服务的安全性,服务端实现的微服务接口通常都带有一定的权限校验机制,由于我们使用了微服务,原本一个应用被拆成了多个模块,所以程序员不得不多次实现校验逻辑,当这套校验逻辑需要修改时,程序员需要修改多个应用,加重了开发人员的负担
针对以上问题,一个常用的解决方案是使用API网关
API网关也简称为网关,网关通常也是单独一个服务,通常是后端的唯一入口,网关的设计模式主要是门面模式,网关就是类似于整个微服务的架构,所有的外部客户端访问后端服务时,都必须要经过网关来进行调度和过滤。
网关的核心功能:
1.权限控制: 作为微服务的入口,对用户的权限进行校验,如果校验失败则进行拦截
2.动态路由:一切请求先经过网关,但网关不进行业务处理,而是根据某种规则,将请求妆发到某一个微服务
3.负载均衡:当路由的目标服务有多个时,还需要进行负载均衡
4.限流:请求流量过高时,按照网关中的配置对微服务能够接受的流量进行放行,避免服务压力过大
2.常见的网关实现
业界常用的网关方式众多,技术方案成熟,开源产品丰富,如Nginx、Kong、Zuul、Spring Cloud Gateway等。以下介绍两种常见网关方案:
- Zuul:Netflix开源的API网关组件,是Spring Cloud Netflix子项目核心组件之一,可与Eureka、Ribbon、Hystrix等配合使用。在Spring Cloud Finchley正式版前,Spring Cloud推荐使用Netflix的Zuul(指Zuul 1.X)。但Netflix在2018年宣布部分组件进入维护状态,不再开发新特性,其中包含Zuul。
- Spring Cloud Gateway:Spring Cloud全新的API网关项目,基于Spring + Spring Boot等技术开发,旨在替代Zuul,为微服务架构提供简单有效的请求转发途径,并提供安全性、监控/指标和弹性等横切关注点。
3.Spring Cloud Gateway的快速上手
注意:这里我是基于我前面的代码来使用的,各位读者视自己的情况而定
1.创建一个网关服务
2.引入网关依赖
由于网关设计到Nacos上的服务,负载均衡,所以还要额外将这两个依赖引入网关工程的pom文件中,所以,在网关工程中的pom文件引入下面的依赖
<!--网关依赖--><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>
3.编写启动类
@SpringBootApplication
public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class,args);}
}
4.添加Gateway的路由配置
创建appication.yml文件,添加响应的配置,添加的配置有网关的端口号,Nacos服务发现的配置项和网关对应的配置项,如一下配置
server:port: 10030 #网关端口号,随便配置一个即可,只要端口号不冲突
spring:application:name: gatewaycloud:nacos:discovery:server-addr: 8.134.130.95:10020 #Nacos服务发现的配置gateway:routes:- id: orders-service #路由规则id, 随便起, 不重复即可uri: lb://orders-service/ #目标服务地址predicates: #路由条件- Path=/order/**,/feign/**- id: product-serviceuri: lb://product-service/predicates:- Path=/product/**
配置字段说明:
1. id:自定义路由,随便起,不重复即可
2. uri:目标服务地址,支持普通uri和 lb://应用注册的服务名称 ,其中lb表示负载均衡,lb:// 方式表示从注册中心获取的服务地址
3.predicate:路由条件,根据匹配结果决定是否将请求转发到对应的微服务中,上述代码中,我们将符合Path规则的一切请求都有网关转发到uri参数指定的地址(也就是uri指定的注册在Nacos上的微服务)
5.测试网关
启动网关服务,并重启订单服务和产品服务
1.通过网关访问product-service服务,url和predicates的Path条件匹配成功,则成功访问product-service服务
不匹配,则会报404,如下图
2.通过网关访问订单服务,url匹配成功的话,就会成功访问订单服务
3.访问订单服务中的其他服务,成功访问
4.Predicate
Predicate是Java8提供的一个函数式编程接口,它用于接收一个参数并返回一个布尔值,用于请求校验,请求参数的校验,Prdicate里面的核心方法就是test()方法,如下面截图
1.代码演示---判断一个字符串是否是空字符串
1.定义一个Predicate,通过实现Predicate接口
/*** 判断字符串是否为空* true ->空字符串* false -> 非空字符串*/
public class StringPredicate implements Predicate<String> {@Overridepublic boolean test(String s) {return s==null||s.isEmpty();}}
2.编写测试方法:
@Testpublic void Test(){Predicate predicate=new StringPredicate();System.out.println(predicate.test(""));System.out.println(predicate.test("aa"));}
运行截图:
2.Predicate的其他写法
1.匿名内部类写法
代码演示:
/*** 匿名内部类*/@Testpublic void Test2(){Predicate<String> predicate=new Predicate<String>() {@Overridepublic boolean test(String s) {return s==null||s.isEmpty();}};System.out.println(predicate.test(""));System.out.println(predicate.test("aa"));}
运行截图
2.lambda表达式写法
代码演示:
/*** lambda表达式*/@Testpublic void Test3(){Predicate<String> predicate= s -> s==null||s.isEmpty();System.out.println(predicate.test(""));System.out.println(predicate.test("aa"));}
运行截图:
3.Predicate中的其他方法
1.negate()方法
negate() 是用来对Predicate返回结果取反的方法,如下图
代码演示:
/*** 取反->negate()*/@Testpublic void test(){Predicate<String> predicate= s -> s==null||s.isEmpty();System.out.println(predicate.negate().test(""));System.out.println(predicate.negate().test("aa"));}
运行截图:
2.and()方法
and()方法其实就是条件A&&条件B,即当前调用and()方法的predicate的test方法&&other的test方法
代码演示:
/*** and* 字符串不为空,且字符串有数字组成 "aa","bb"*/@Testpublic void test2(){Predicate<String> predicate= s-> s==null||!s.isEmpty();Predicate<String> predicate1=s -> s.chars().allMatch(Character::isDigit);System.out.println(predicate.and(predicate1).test("12"));System.out.println(predicate.and(predicate1).test(""));System.out.println(predicate.and(predicate1).test("a1"));}
运行截图:
3.or()
or()方法其实就是条件A||条件B,即当前调用or()方法的predicate的test方法||other的test方法
代码演示:
/*** or* 判断字符串是不是aa或者bb*/@Testpublic void test3(){Predicate<String> predicate1=s-> s.isEmpty();Predicate<String> predicate=s -> s.equals("aa");Predicate<String> predicate2=s -> s.equals("bb");System.out.println(predicate2.or(predicate1).test("bb"));System.out.println(predicate2.or(predicate1).test("cc"));}
运行截图:
5. Route Predicate Factories
Route Predicate Factories(路由断言工厂),在Spring Cloud Gateway中,Predicate提供了路由规则的匹配机制
在配置文件中写的断言规则只是字符串,这些字符串会被Route Predicate Factories读取并处理,转变为路由判断的条件
Spring Cloud Gateway默认提供了很多Route Predicate Factory,这些Predicate会分别匹配HTTP请求中的不同属性,并且多个Predicate会默认为and逻辑组合
1.通过时间匹配
Predicate支持设置一个时间,在请求转发的时候,可以通过判断是否在这个时间之前转发或者之后转发。比如现在我设置只有在2025年5月29号时,该请求才能转发请求,在这之前,不会将请求转发,我就可以添加一下配置:
Spring是通过ZoneDateTimela来对时间进行的对比,ZoneDateTime是Java8中日期时间功能里,用于表示带时区的日期与时间信息的类,ZoneDateTime支持通过时区来设置时间
添加完以上配置,重启网关服务,去调用订单服务,发现服务调用成功
如果添加一个Before配置,如下图
此时,重启网关服务,此时就会报404,因为此时访问时间已经在Before的条件的时间之后
还有很多匹配规则,可以去Spring官网查看,这里就不一 一说明了
6. Gateway Filter Factories(网关过滤器工厂)
Predicate决定了请求由哪一个路由处理,如果需要在请求处理前后添加一些逻辑,我们此时就需要用到Filter(过滤器)
Filter分为两种类型:Pre类型和Post类型
Pre类型过滤器:路由处理之前执行(请求转发到后端服务之前执行),在Pre类型过滤器中可以做身份验证和限流登操作
Post类型过滤器:请求执行完后完成,也就是将结果返回给客户端之前执行
Spring Cloud Gateway中内置了很多FIlter,用于拦截和链式处理web请求,比如权限校验,访问超时等设定
Spring Cloud Gateway从作用范围上,可以将Filter分为GatewayFilter和GlobalFilter
GatewayFilter:应用到单个路由或者一个分组的路由上
GlobalFilter:应用到所有的路由上,也就是对所有的请求生效
6.1 GatewayFilter
GateFilter同Predicate类似,都是在配置文件中配置,每个过滤器的逻辑都是固定的
1.为当前请求添加参数---AddRequestParameter,添加下面的配置
2. 为当前请求添加Header---AddRequestHeader
3.从当前请求中删除某一个Header信息---RemoveRequestHeader
4.为响应结果添加Header---AddResponseHeader
过程图:
5.从响应结果中删除某个Header---RemoveResponseHeader
此时通过Postman发现,p6方法中添加的Header信息已经被删除
6.默认过滤器---default-filters
添加一个filter并将其应用到所有路由,并配置了重传次数
订单服务
产品服务
6.2 GlobalFilter
GlobalFilter是Spring Cloud Gateway中的全局过滤器,它和Gateway的作用是相同的,但是GlobalFilter会应用到所有的路由请求上,全局过滤器通常用于实现与安全性,性能监控和日志记录等相关的全局功能
Spring Cloud Gateway内置的全局过滤器有很多,比如:
1.Gateway Metrics Filter:网关指标,提供监控指标
2.Forward Routing Filter:用于本地forword,请求不转发到下游服务器
3.LoadBalancer Client Filter:针对下游服务,实现负载均衡
1.快速上手---以Gateway Metrics Filter为例
在网关工程中添加下面的依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
然后在网关工程中的配置文件中添加相关的配置,如下图
spring:cloud:gateway:metrics:enabled: true
management:endpoints:web:exposure:include: "*"endpoint:health:show-details: alwaysshutdown:enabled: true
重启网关工程,通过下面的链接去访问,将会显示所有监控的信息
链接:127.0.0.1:10030/actuator
2.过滤器的执行顺序
一个项目中,既有GatewayFilter,又有GlobalFilter,执行的先后顺序是什么呢?
请求路由后,网关会把当前项目中的GatewayFilter和GlobalFilter合并到一个过滤器链中,并进行排序,依次执行过滤器
每一个过滤器都必须指定一个int类型的order值,默认值为0,表示过滤的优先级,order值越小,优先级越高,执行顺序越靠前。
1、Filter通过实现Order接口或者天剑@Order注解来指定Order值
2、Spring Cloud Gateway提供的Filter有Spring指定,用户也可以自定义Filter,由用户指定
3、当过滤器的Oorder值一样,会按照dafaultFilter>GatewayFlter>ClobalFilter的顺序来执行
7.自定义过滤器
Spring Cloud Gateway提供了过滤器的扩展功能,开发者可以根据实际业务来自定义过滤器,同样自定义过滤器也支持GatewayFilter和GlobalFilter两种
1.自定义GatewayFilter
自定义GatewayFilter需要去实现对应的接口GatewayFilterFactory,SpringBoot默认帮我们实现的抽象类是AbstractGatewayFilterFactory,可以直接使用,由于我们还要声明该过滤器的优先级,所以还要去实现Ordered接口,分别去重写里面的方法
其次,对于过滤器来说,所有的路由配置都是通过配置文件来实现的,配置文件中写的是一些字符串,在应用启动时,Gateway会将这些字符串解析为内部数据结构,当请求达到网关时,Gateway会从解析后的配置提取参数,并传给对应的Filter实现类,所以要实现一个自定义GAtewayFilter,我们还要创建一个对应类型的数据类,作为自定义Gateway的参数类型
完整实现:
对应的参数类---CustomConfig
@Data
public class CustomConfig {private String name;
}
自定义GAtewayFilter的实现代码---CustomGatewayFilterFactory
@Slf4j
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomConfig> implements Ordered {public CustomGatewayFilterFactory() {super(CustomConfig.class);}@Overridepublic GatewayFilter apply(CustomConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//Pre -> 执行请求 -> Postlog.info("Pre Filter,config:{}",config);//pre类型过滤器代码逻辑return chain.filter(exchange).then(Mono.fromRunnable(()->{log.info("Post Filter,config:{}",config);}));}};}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}
}
代码解析:
1.类名统一以GatewayFilter结尾,因为默认情况下,过滤器的name会采用该定义类的前缀,以上面的自定义GateawayFilter为例,此时自定义GateawayFilter的name就是Custom
2.apply方法中同时包含Pre和Post,then方法就是Post类型的逻辑
3.CustomConfig是一个配置类,也yml配置对应
4.CustomGatewayFilter需要交给Spring管理,所以需要添加@Component注解
5.getOder表示该过滤器的优先级,值越大,优先级越低
最后去配置文件中添加相关配置
测试:
2.自定义GlobalFilter
GlobalFilter的实现比较简单,它不需要额外的配置,只需要实现GlobalFilter接口即可,自动会过滤所有的Filter
代码实现:
@Slf4j
@Component
public class CustomGlobalFilter implements GlobalFilter,Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("Global Filter Pre...");return chain.filter(exchange).then(Mono.fromRunnable(()->{log.info("Global Filter Post...");}));}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}
}
测试:
相关文章:

《Spring Cloud Gateway 快速入门:从路由到自定义 Filter 的完整教程》
1.网关介绍 在前面的学习中,我们通过Eureka和Nacos解决了辅助注册,使用Spring Cloud LoadBalance解决了负载均衡的问题,使用OpenFeign解决了远程调用的问题。 但是当前的所有微服务的接口都是直接对外暴露的,外部是可以直接访问…...

第3节 Node.js 创建第一个应用
Node.js 非常强大,只需动手写几行代码就可以构建出整个HTTP服务器。事实上,我们的Web应用以及对应的Web服务器基本上是一样的。 在我们创建Node.js第一个"Hello, World!"应用前,让我们先了解下Node.js应用是由哪几部分组成的&…...

我们来学mysql -- “数据备份还原”sh脚本
数据备份&还原 说明执行db_backup_cover.sh脚本 说明 环境准备:来源数据库(服务器A);目标数据库(服务器B)dbInfo.sh脚本记录基本信息 来源库、目标库的ip、port及执行路径 # MySQL 客户端和 mysqldump 的路径 MYSQL_CLIENT"/work/oracle/mysql…...
mkcert实现本地https
1.下载 mkcert 从 mkcert GitHub 发布页 下载适用于 Windows 的版本(如 mkcert-v1.4.4-windows-amd64.exe)。 安装 mkcert 以管理员身份运行命令提示符(CMD),执行以下命令安装并信任本地 CAÿ…...

【排序算法】快速排序详解--附详细流程代码
快速排序算法 介绍 快速排序(Quick Sort)是一种高效的分治排序算法,由英国计算机科学家 Tony Hoare 于 1960 年提出。它是实际应用中最常用的排序算法之一。快速排序的基本思想是:选择一个"基准"(pivot&am…...
Kerberos面试内容整理-会话密钥的协商与使用
在 Kerberos 认证过程中,**会话密钥(Session Key)**扮演着关键角色。会话密钥是由 KDC 临时生成并分发给通信双方用于当前会话的对称加密密钥。与用户密码这类长期密钥不同,会话密钥的生命周期很短,仅在特定的认证会话或服务访问期间有效。这种设计大幅提升了安全性:长期…...

解决各个系统报错TDengine:no taos in java.library.path问题
windows 系统解决办法 在本地上安装一个TD的Windows客户端,注意安装的客户端版本一定要和服务端TD版本完全一致。(或者将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下) 客户端各个历史版本下载链接:TDengin…...

java helloWord java程序运行机制 用idea创建一个java项目 标识符 关键字 数据类型 字节
HelloWord public class Hello{public static void main(String[] args) {System.out.print("Hello,World!");} }java程序运行机制 用idea创建一个java项目 建立一个空项目 新建一个module 注释 标识符 关键字 标识符注意点 数据类型 public class Demo02 {public st…...
LVS-NAT 负载均衡群集
目录 简介 一、LVS 与群集技术基础 1.1 群集技术概述 1.2 负载均衡群集的分层结构 1.3 负载均衡工作模式 二、LVS 虚拟服务器核心组件与配置 2.1 LVS 内核模块与管理工具 2.2 负载调度算法解析 2.3 ipvsadm 管理工具实战 三、NFS 共享存储服务配置 3.1 NFS 服务基础…...

免费文本转语音工具体验:祈风TTS使用
简介:语音生成的另一种方式 现在很多人通过视频记录生活,表达观点。拍摄剪辑不难,配音成了常见难题。部分人对自己的声音不够自信,也有人在特定场景下不便出声。文本转语音工具可以成为解决方案。 常见的TTS(Text To…...
ipv6与p2p的关系
在PCDN(P2P内容分发网络)领域,IPv6与PCDN盒子的关系紧密且相互影响,主要体现在以下几个方面: 一、IPv6的部署推动PCDN盒子普及 地址资源充足 IPv6采用128位地址,解决了IPv4地址枯竭的问题,为PC…...

JS和TS的区别
JavaScript 与 TypeScript 的主要区别和特性对比 1. 基础定义 JavaScript 是一种动态、弱类型的编程语言,广泛应用于前端开发以及通过 Node.js 扩展到后端开发。TypeScript 则是 JavaScript 的超集,它在 JavaScript 的基础上添加了静态类型系统和其他增…...

Python实现P-PSO优化算法优化BP神经网络分类模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 随着人工智能技术的快速发展,神经网络在分类任务中展现了强大的性能。BP(Back Propagation&…...

Linux --进度条小程序更新
这里使用随机数来模拟下载量,来实现一个下载进度更新的小程序 main.c 的代码,其中downlod这个函数使用的是函数指针,如果有多个进度条函数可以传入进行多样化的格式下载显示,还需要传入一个下载总量,每次"下载以…...
JVM——回顾:JVM的起源、特性与系统构成
引入 在当今数字化时代,Java语言及其运行环境Java虚拟机(JVM)在软件开发领域占据着举足轻重的地位。从大型企业级应用到各类移动应用,JVM凭借其独特的特性和强大的功能,为开发者提供了高效且稳定的运行环境。 JVM的起…...
实现MPC钱包
多方计算(MPC,Multiparty Computation)钱包是一种利用密码学技术实现的加密货币钱包,它允许多个参与者共同生成和管理钱包的私钥,而无需将私钥暴露给任何单个参与者。这种钱包具有高度的安全性和隐私性。实现一个 MPC …...
每日算法刷题Day19 5.31:leetcode二分答案3道题,用时1h
6. 475.供暖器(中等,学习check函数双指针思想) 475. 供暖器 - 力扣(LeetCode) 思想 1.冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。在加热器的加热半径范围内的每个房屋都可以获得供暖。现在,给出…...
【线上故障排查】缓存热点Key导致Redis性能下降的排查与优化
一、高频面试题 什么是缓存热点Key?它会对Redis性能产生哪些影响? 缓存热点Key是指在某段时间内,被大量请求访问的缓存Key。由于Redis是单线程模型,大量针对热点Key的请求会导致该线程长时间处于忙碌状态,其他请求只能排队等待处理,从而使Redis整体响应延迟增加,吞吐量下…...

关于镜像如何装进虚拟机
本篇文章为感谢小仙猪老师特别编写 本篇文章仅以Ubuntu为例 目录 创建虚拟机 汉化 如果没有China选项 检查网络 创建虚拟机 第一步,创建虚拟机 因为,第一个选项是会把虚拟机的文件放在c盘因此,这里博主选择自定义,然后下一…...
CPU特权级别:硬件与软件协同构建系统安全的基石
在计算机系统的底层架构中,用户模式(User Mode)与内核模式(Kernel Mode)的划分是保障系统安全与稳定的核心机制。这一机制的实现既依赖于CPU硬件的特权级别设计,也离不开操作系统的精细化管理。本文将从硬件…...

智慧体育馆数字孪生,场馆管理智能化
图扑数字孪生智慧体育馆可视化管理平台。通过高精度三维建模,对体育馆建筑结构、设施设备等进行 1:1 虚拟映射,全方位还原场馆物理实体。系统集成多维度传感器数据,实现对人流量、客流密度、区域拥堵指数等信息的实时采集与分析,动…...

回归算法模型之线性回归
哈喽!我是 我不是小upper~ 今天来和大家聊聊「线性回归」—— 这是机器学习里最基础、最直观的算法之一,咱们用一个超简单的例子就能搞懂它! 先看一个生活场景 假设你是房产中介,遇到一个灵魂拷问: 客户有…...

【深度学习】10. 深度推理(含链式法则详解)RNN, LSTM, GRU,VQA
深度推理(含链式法则详解)RNN, LSTM, GRU,VQA RNN 输入表示方式 在循环神经网络(Recurrent Neural Network, RNN)中,我们处理的是一段文字或语音等序列数据。对于文本任务,输入通常是单词序列…...
【Java】在 Spring Boot 中连接 MySQL 数据库
在 Spring Boot 中连接 MySQL 数据库是一个常见的任务。Spring Boot 提供了自动配置功能,使得连接 MySQL 数据库变得非常简单。以下是详细的步骤: 一、添加依赖 首先,确保你的pom.xml文件中包含了 Spring Boot 的 Starter Data JPA 和 MySQ…...
影响服务器稳定性的因素都有什么?
服务器的稳定性会影响到业务是否能够持续运行,用户在进行访问网站的过程中是否出现页面卡顿的情况,本文就来了解一下都是哪些因素影响着服务器的稳定性。 服务器中的硬件设备是保证服务器稳定运行的基础,企业选择高性能的处理器和大容量且高速…...

【Qt】Bug:findChildren找不到控件
使用正确的父对象调用 findChildren:不要在布局对象上调用 findChildren,而应该在布局所在的窗口或控件上调用。...
GitHub 趋势日报 (2025年05月30日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 833 agenticSeek 789 prompt-eng-interactive-tutorial 466 ai-agents-for-beginn…...

【linux】linux进程概念(四)(环境变量)超详细版
小编个人主页详情<—请点击 小编个人gitee代码仓库<—请点击 linux系列专栏<—请点击 倘若命中无此运,孤身亦可登昆仑,送给屏幕面前的读者朋友们和小编自己! 目录 前言一、基本概念二、认识常见的几个环境变量echo $ 查看某个环境变量env 显示…...
Qt程序添加调试输出窗口:CONFIG += console
目录 1.背景 2.解决方案 3.原理详解 4.控制台窗口的行为 5.条件编译(仅调试模式显示控制台) 6.替代方案 7.总结 1.背景 在Qt程序开发中,开发者经常遇到这样的困扰: 开发机上程序运行正常 发布到其他机器后程序无法启动 …...

从零开始的二三维CAD|CAE软件: 解决VTK,DICOM体素化-失效问题.
背景: 在从零开始的二三维软件开发中, 需要加载CT的dicoms影像文件, 并将其序列化之后的数据,体素化 可惜..vtk的c#库,将其体素化的时候,竟然失败... 使用vtkDicomReader ,设置 Dicom文件夹读取,竟然不停的失败...从网上找了一些版本.也没啥可用的资料... 解决办法: 直接…...