Gateway与WebFlux的整合

server/2025/1/18 14:24:08/

 WebFlux:HandlerMapping

HandlerMapping下主要分为2个分支:AbstractUrlHandlerMapping和AbstractHandlerMethodMapping,其中AbstractUrlHandlerMapping用于url与handler的匹配,AbstractHandlerMethodMapping用于HandlerMethod与handler的匹配,2者均继承于AbstractHandlerMapping,更详细的后续会单独开一篇文章。

AbstractHandlerMapping

java">public abstract class AbstractHandlerMapping extends ApplicationObjectSupportimplements HandlerMapping, Ordered, BeanNameAware {@Overridepublic Mono<Object> getHandler(ServerWebExchange exchange) {return getHandlerInternal(exchange).map(handler -> {if (logger.isDebugEnabled()) {logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);}ServerHttpRequest request = exchange.getRequest();if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(exchange) : null);CorsConfiguration handlerConfig = getCorsConfiguration(handler, exchange);config = (config != null ? config.combine(handlerConfig) : handlerConfig);if (!this.corsProcessor.process(config, exchange) || CorsUtils.isPreFlightRequest(request)) {return REQUEST_HANDLED_HANDLER;}}return handler;});}protected abstract Mono<?> getHandlerInternal(ServerWebExchange exchange);
}

可以看出这里的核心方法是getHandler,而内部的真实实现位于getHandlerInternal,这是个抽象方法并未实现。

WebFlux:HandlerAdapter

这里简单介绍下:

  • HandlerFunctionAdapter:支持HandlerFunction的实例,业务实现方法为HandlerFunction#handle
  • RequestMappingHandlerAdapter:这是日常业务开发用到最多的,对应的支持类型为HandlerMethod,业务方法为各自定义的方法,无具体的限制方法
  • SimpleHandlerAdapter:要求handler的类型为WebHandler或者其子类的实现类,业务实现方法为WebHandler#handle
  • WebSocketHandlerAdapter:要求handler的类型为WebSocketHandler或者其子类的实现类,业务实现方法为WebSocketHandler#handle,这里涉及到WebSocketService的处理,支持webSocket协议的处理

WebFlux:HandlerResultHandler

简单介绍下:

  • ResponseBodyResultHandler:支持类或者方法上有@ResponseBody注解的数据处理
  • ResponseEntityResultHandler:支持返回值是HttpEntity或其子类实例(不能是RequestEntity及其子类的实例)、HttpHeaders及其子类实例的数据处理
  • ServerResponseResultHandler:支持返回值是ServerResponse实例的数据处理
  • ViewResolutionResultHandler:支持CharSequence、Rendering、Model、Map、View、非简单属性及其子类实例的数据处理,这里的简单类型如下
    java">public static boolean isSimpleValueType(Class<?> type) {return (Void.class != type && void.class != type &&(ClassUtils.isPrimitiveOrWrapper(type) ||Enum.class.isAssignableFrom(type) ||CharSequence.class.isAssignableFrom(type) ||Number.class.isAssignableFrom(type) ||Date.class.isAssignableFrom(type) ||Temporal.class.isAssignableFrom(type) ||URI.class == type ||URL.class == type ||Locale.class == type ||Class.class == type));}
    

Gateway:GatewayAutoConfiguration

java">@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {@Beanpublic FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {return new FilteringWebHandler(globalFilters);}@Beanpublic RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator,GlobalCorsProperties globalCorsProperties, Environment environment) {return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties, environment);}}

这里主要标出主流程涉及到的类:

  • RoutePredicateHandlerMapping:负责路由匹配
  • FilteringWebHandler:负责过滤器的执行

Gateway:RoutePredicateHandlerMapping

java">public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {private final FilteringWebHandler webHandler;@Overrideprotected Mono<?> getHandlerInternal(ServerWebExchange exchange) {// don't handle requests on management port if set and different than server portif (this.managementPortType == DIFFERENT && this.managementPort != null&& exchange.getRequest().getURI().getPort() == this.managementPort) {return Mono.empty();}exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());return lookupRoute(exchange)// .log("route-predicate-handler-mapping", Level.FINER) //name this.flatMap((Function<Route, Mono<?>>) r -> {exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);if (logger.isDebugEnabled()) {logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r);}exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);return Mono.just(webHandler);}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);if (logger.isTraceEnabled()) {logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]");}})));}protected Mono<Route> lookupRoute(ServerWebExchange exchange) {return this.routeLocator.getRoutes()// individually filter routes so that filterWhen error delaying is not a// problem.concatMap(route -> Mono.just(route).filterWhen(r -> {// add the current route we are testingexchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());return r.getPredicate().apply(exchange);})// instead of immediately stopping main flux due to error, log and swallow it.doOnError(e -> logger.error("Error applying predicate for route: " + route.getId(), e)).onErrorResume(e -> Mono.empty()))// .defaultIfEmpty() put a static Route not found// or .switchIfEmpty()// .switchIfEmpty(Mono.<Route>empty().log("noroute")).next()// TODO: error handling.map(route -> {if (logger.isDebugEnabled()) {logger.debug("Route matched: " + route.getId());}validateRoute(route, exchange);return route;});/** TODO: trace logging if (logger.isTraceEnabled()) {* logger.trace("RouteDefinition did not match: " + routeDefinition.getId()); }*/}}
lookupRoute方法通过AsyncPredicate选择出对应的路由,并将路由id记录到ServerWebExchange的属性gatewayPredicateRouteAttr中,getHandlerInternal中则移除gatewayPredicateRouteAttr属性,将整个路由放入ServerWebExchange的gatewayRoute属性中,最后返回FilteringWebHandler

Gateway:FilteringWebHandler

java">public class FilteringWebHandler implements WebHandler {protected static final Log logger = LogFactory.getLog(FilteringWebHandler.class);private final List<GatewayFilter> globalFilters;public FilteringWebHandler(List<GlobalFilter> globalFilters) {this.globalFilters = loadFilters(globalFilters);}private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {return filters.stream().map(filter -> {GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);if (filter instanceof Ordered) {int order = ((Ordered) filter).getOrder();return new OrderedGatewayFilter(gatewayFilter, order);}return gatewayFilter;}).collect(Collectors.toList());public Mono<Void> handle(ServerWebExchange exchange) {Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);List<GatewayFilter> gatewayFilters = route.getFilters();List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);combined.addAll(gatewayFilters);// TODO: needed or cached?AnnotationAwareOrderComparator.sort(combined);if (logger.isDebugEnabled()) {logger.debug("Sorted gatewayFilterFactories: " + combined);}return new DefaultGatewayFilterChain(combined).filter(exchange);}
}
FilteringWebHandler实现了WebHandler接口作为当前路由的handler返回,而在WebFlux中,对应的handlerAdapter则为SimpleHandlerAdapter,这里会调用handle方法,即FilteringWebHandler#handle,该方法中将路由中定义的filter即GatewayFilter和全局filter即GlobalFilter进行拼装并排序,构建了DefaultGatewayFilterChain过滤器链条:
java">private static class DefaultGatewayFilterChain implements GatewayFilterChain {@Overridepublic Mono<Void> filter(ServerWebExchange exchange) {return Mono.defer(() -> {if (this.index < filters.size()) {GatewayFilter filter = filters.get(this.index);DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this, this.index + 1);return filter.filter(exchange, chain);}else {return Mono.empty(); // complete}});}}

可以看出这里会逐个执行所有的过滤器逻辑

Gateway:默认全局过滤器

java">public class GatewayAutoConfiguration {@Bean@ConditionalOnEnabledGlobalFilterpublic AdaptCachedBodyGlobalFilter adaptCachedBodyGlobalFilter() {return new AdaptCachedBodyGlobalFilter();}@Bean@ConditionalOnEnabledGlobalFilterpublic RemoveCachedBodyFilter removeCachedBodyFilter() {return new RemoveCachedBodyFilter();}@Bean@ConditionalOnEnabledGlobalFilterpublic RouteToRequestUrlFilter routeToRequestUrlFilter() {return new RouteToRequestUrlFilter();}@Bean@ConditionalOnEnabledGlobalFilterpublic ForwardRoutingFilter forwardRoutingFilter(ObjectProvider<DispatcherHandler> dispatcherHandler) {return new ForwardRoutingFilter(dispatcherHandler);}@Bean@ConditionalOnEnabledGlobalFilterpublic ForwardPathFilter forwardPathFilter() {return new ForwardPathFilter();}@Bean@ConditionalOnEnabledGlobalFilterpublic WebsocketRoutingFilter websocketRoutingFilter(WebSocketClient webSocketClient, WebSocketService webSocketService,ObjectProvider<List<HttpHeadersFilter>> headersFilters) {return new WebsocketRoutingFilter(webSocketClient, webSocketService, headersFilters);}@Beanpublic WeightCalculatorWebFilter weightCalculatorWebFilter(ConfigurationService configurationService,ObjectProvider<RouteLocator> routeLocator) {return new WeightCalculatorWebFilter(routeLocator, configurationService);}}

可以看出默认的全局过滤器均需手动去开启,WeightCalculatorWebFilter为GateFilter的实现,用于权重的计算,默认会配置


http://www.ppmy.cn/server/159368.html

相关文章

1.3变革之力:Transformer 如何重塑深度学习的未来

变革之力:Transformer 如何重塑深度学习的未来 在深度学习的历史上,Transformer 是一项标志性的突破,彻底改变了自然语言处理(NLP)和机器学习领域的格局。自从它在2017年由 Vaswani 等人提出以来,Transformer 便成为了处理序列数据的标准架构,其强大的表达能力和计算效…

Python与Excel:开启自动化办公新时代

引言 在当今数字化办公的大环境下&#xff0c;日常工作中处理Excel表格的任务愈发频繁且繁杂。传统的手动操作不仅耗时费力&#xff0c;还容易出错。而Python作为一门功能强大且应用广泛的编程语言&#xff0c;为我们实现Excel办公自动化提供了高效的解决方案。借助Python的丰…

国内汽车法规政策标准解读:GB/T 44464-2024《汽车数据通用要求》

目录 背景介绍 概要General 标准适用范围 重要规定与要求 汽车数据安全管理体系要求 扩展&#xff1a;汽车数据安全管理体系(DSMS) 个人信息保护要求 个人信息处理通用要求 个人同意 个人信息收集 个人信息存储 个人信息使用 个人信息传输 个人信息删除 个人信息…

网络安全之sql注入

1.何为Sql注入&#xff1f; 所谓SQL注入&#xff0c;就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串&#xff0c;最终达到欺骗服务器执行恶意的SQL命令。具体来说&#xff0c;它是利用现有应用程序&#xff0c;将&#xff08;恶意的&#xff09;SQL命令注…

汇编语言:基于x86处理器考前笔记 | 第七章 整数运算

一、移位与循环移位指令 指令类型&#xff08;都会改变 CF&#xff09; 逻辑移位&#xff1a;SHL&#xff08;逻辑左移&#xff09;、SHR&#xff08;逻辑右移&#xff09;。例如&#xff0c;SHL 指令将操作数左移&#xff0c;最低位补 0&#xff0c;最高位进入进位标志 CF&am…

Objective-C语言的数据库交互

Objective-C语言的数据库交互 引言 在现代应用程序开发过程中&#xff0c;数据库在数据存储和管理方面起着至关重要的作用。对于iOS应用开发者而言&#xff0c;掌握如何在Objective-C中与数据库交互显得尤为重要。本文将全面探讨Objective-C的数据库交互&#xff0c;包括SQLi…

【C++】构造函数与析构函数

写在前面 构造函数与析构函数都是属于类的默认成员函数&#xff01; 默认成员函数是程序猿不显示声明定义&#xff0c;编译器会中生成。 构造函数和析构函数的知识需要建立在有初步类与对象的基础之上的&#xff0c;关于类与对象不才在前面笔记中有详细的介绍&#xff1a;点我…

20250117在Ubuntu20.04.6下使用灵思FPGA的刷机工具efinity刷机

20250117在Ubuntu20.04.6下使用灵思FPGA的刷机工具efinity刷机 2025/1/17 18:30 缘起&#xff1a;做Rockchip的项目RK3566/RK3588&#xff0c;由于编译服务器是ubuntu&#xff0c;RK3566/RK3588有Linux/Ubuntu下的刷机工具。 就顺手要了一下易灵思的FPGA的刷机工具&#xff0c;…