Diseño del código fuente de Spring
Pero el alcance agregado de la dependencia de resaca no está configurado como proporcionado, lo que resulta en que mientras se agregue esta dependencia, se agregará la dependencia de resaca. Sucede que la puerta de enlace también usa esta dependencia y nuestra puerta de enlace usa Spring-Cloud-Gateway. Esto resultó en que el contenedor web Reactive de Netty de Spring-Cloud-Gateway fuera reemplazado por el contenedor web Reactive de Undertow, lo que resultó en una serie de problemas de incompatibilidad con Spring-Cloud-Gateway.
Sabemos que la capa inferior de Spring-Cloud-Gateway en realidad se basa en Spring Boot. Primero, echemos un vistazo a los principios de selección para los cuales se inicializa el contenedor web Spring Boot: Primero, el primer paso es determinar qué WebApplicationType se basa en si la clase existe:
tipo de aplicación web
Se puede ver en el código fuente que cuando hay WEBFLUX_INDICATOR_CLASS pero no WEBMVC_INDICATOR_CLASS y JERSEY_INDICATOR_CLASS, se considera un entorno reactivo. Si todas las clases_indicadores_SERVLET se consideran entornos de servlet. De hecho, también se puede ver que si se introducen spring-web y spring-webflux, en realidad es un entorno SERVLET. Si nada de lo anterior es cierto, entonces es un entorno sin contenedor web. En Spring-Cloud-Gateway, es un entorno reactivo.
Si es un entorno reactivo, se creará un contenedor web utilizando los beans de implementación de la organización. spring framework.web.reactive.serverfactory. Actualmente hay cuatro implementaciones (Spring-boot 2.7.x):
Cuál se usará realmente para ver qué Bean se registrará en ApplicationContext:
Configuración de fábrica del servidor web reactivo
p>Como se puede ver en el código original, cada configuración tiene @ ConditionalonMissingBean (ReactiveWebServiceFactory. class) y condiciones para determinar si existe una clase correspondiente al contenedor, como @ ConditionalonClass ({Undertow. clase}). @configuration (métodos proxybean = false) es desactivar el proxy entre beans en esta configuración para acelerar la carga.
Debido a que cada configuración tiene @ConditionalonMissingBean (ReactiveWebServerFactory.Class), en realidad se garantiza que incluso si se cumplen las condiciones de múltiples configuraciones, al final solo habrá una ReactiveWebServerFactory.
Entonces, cuando se cumplen varias condiciones, ¿cuál debería cargarse primero? Depende del código fuente aquí:
configuración automática de fábrica del servidor web reactivo
Se puede ver que se importa en el orden de EmbeddedTomcat, EmbeddedJetty, EmbeddedUndertow y Embedded Dnetty, también Eso es decir, siempre que se agregue cualquier contenedor web (como Undertow) a sus dependencias, eventualmente se creará un contenedor asincrónico basado en ese contenedor web, no basado en netty.
En primer lugar, el documento oficial de Spring Cloud Gateway dice:
Es decir, Spring Cloud Gateway solo se puede ejecutar en el entorno Netty. ¿Por qué es esto? Durante el diseño se partió del supuesto de que el contenedor sólo podía ser reticulado. Al desarrollar varios filtros integrados y complementos de filtro de Spring Cloud Gateway, una gran cantidad de código actualmente supone que es Netty, como la clase de herramienta ServerWebExchangeUtils utilizada para almacenar en caché el filtro principal:
ServerWebExchangeUtils
Se puede ver en el código fuente que el código piensa directamente que BufferFactory en la respuesta es NettyDataBufferFactory, pero en el caso de otros contenedores web, actualmente debería ser DefaultDataBufferFactory, por lo que habrá excepciones. Sin embargo, en versiones posteriores a la v3.0.5, este fuerte cambio se ha solucionado. Referencia:/Spring-Cloud/Spring-Cloud-Gateway/Commit/68dc 355119e 057 af 1e4f 664 c 814c 5.
Esto realmente allana el camino para la compatibilidad con todos los contenedores web. Entonces, ¿existe algún plan para ser compatible con todos los contenedores web? Se ha planificado y todavía se está haciendo. Se ha realizado durante casi cuatro años y debería realizarse pronto, lo que significa que todas las pruebas unitarias deben volver a ejecutarse o incluso rediseñarse. Puede verificar esto a través de este problema: Compatibilidad con la ejecución de puerta de enlace con otros contenedores de reacción basados en netty #145.
Ver el progreso de la compatibilidad.