Spring WebFlux, Al igual que Spring MVC, está diseñado en un patrón de punto único de entrada (controlador frontal), donde un WebHandler central, DispatcherHandler, proporciona el algoritmo general de procesamiento de solicitudes y el trabajo real. se realiza mediante componentes configurables -delegados. Este modelo es flexible y admite diferentes flujos de trabajo.

DispatcherHandler descubre los beans delegados que necesita desde la configuración de Spring. También está diseñado para actuar como un Spring Bean e implementa ApplicationContextAware para acceder al contexto en el que se está ejecutando. Si DispatcherHandler se declara con el nombre de bean webHandler, entonces, a su vez, lo descubre WebHttpHandlerBuilder, que ensambla la cadena de procesamiento de solicitudes.

La configuración de Spring en una aplicación WebFlux generalmente contiene:

  • DispatcherHandler con nombre de bean webHandler;

  • WebFilter y WebExceptionHandler beans;

  • DispatcherHandler beans especial;

  • Y más.

La configuración se pasa a WebHttpHandlerBuilder para cofnstruir el procesamiento de la cadena como se muestra en el siguiente ejemplo:

Java

ApplicationContext context = ...
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build();
Kotlin

val context: ApplicationContext = ...
val handler = WebHttpHandlerBuilder.applicationContext(context).build()
        

El HttpHandler recibido está listo para usarse con el adaptador de servidor.

1.3.1. Tipos de beans especializados

DispatcherHandler delega a beans especiales el procesamiento de solicitudes y la emisión de respuestas apropiadas. Por "beans especiales" nos referimos a instancias Object administradas por Spring que implementan contratos marco WebFlux. Por lo general, tienen contratos integrados, pero puede personalizar sus propiedades, ampliarlas o reemplazarlas.

La siguiente tabla enumera los beans especiales que descubre DispatcherHandler. Tenga en cuenta que también hay otros tipos de beans que se definen en un nivel inferior.

Tipo de frijol Explicación

HandlerMapping

Asigna una solicitud de controlador. La asignación se basa en algunos criterios, cuyos detalles dependen de la implementación de HandlerMapping: controladores anotados, asignaciones de patrones de URL simples, etc.

HandlerMapping principal las implementaciones son RequestMappingHandlerMapping para métodos anotados con @RequestMapping, RouterFunctionMapping para rutas funcionales de endpoints y SimpleUrlHandlerMapping para plantillas explícitas. rutas de URI de registro e instancias de WebHandler.

HandlerAdapter

Ayuda a DispatcherHandler a llamar al controlador asignado a la solicitud, independientemente de cómo se llame realmente a ese controlador. Por ejemplo, llamar a un controlador anotado requiere resolución de anotaciones. El objetivo principal del HandlerAdapter es proteger al DispatcherHandler de dichos detalles.

HandlerResultHandler

Procesa el resultado de la llamada del controlador y completa la respuesta.

Configuración de WebFlux

Las aplicaciones pueden declarar beans de infraestructura necesarios para procesar solicitudes. Sin embargo, en la mayoría de los casos la configuración de WebFlux es el mejor punto de partida. Declara los beans necesarios y proporciona una API de devolución de llamada de configuración de nivel superior para la configuración.

Spring Boot se basa en la configuración de WebFlux para configurar Spring WebFlux y proporciona muchas opciones convenientes adicionales.

1.3.3. Manejo

DispatcherHandler procesa las solicitudes de la siguiente manera:

  • A cada HandlerMapping se le pide que encuentre un controlador adecuado y se utiliza la primera coincidencia.

  • Si se encuentra un controlador, se ejecuta a través del HandlerAdapter correspondiente, que expone el valor de retorno después de la ejecución como HandlerResult .

  • HandlerResult se pasa al HandlerResultHandler correspondiente para completar el procesamiento escribiendo en la respuesta directamente o usando una vista de renderizado.

1.3.4. Procesando los resultados

El valor de retorno después de llamar al controlador a través de HandlerAdapter se empaqueta como un HandlerResult, junto con algún contexto adicional, y se pasa al primer HandlerResultHandler, que contiene una declaración sobre su soporte. La siguiente tabla muestra las implementaciones disponibles de HandlerResultHandler, todas las cuales están declaradas en la configuración de WebFlux:

Tipo de controlador de resultados Valores de retorno Orden predeterminado

ResponseEntityResultHandler

ResponseEntity, normalmente de instancias de anotación @Controller.

0

ServerResponseResultHandler

ServerResponse, normalmente desde puntos finales funcionales.

0

ResponseBodyResultHandler

Procesar valores de retorno de métodos marcados con la anotación @ResponseBody o clases marcadas con la anotación @RestController.

100

ViewResolutionResultHandler

CharSequence, View, Model, Map, Renderizado o cualquier otro Objeto se considera un atributo del modelo.

Integer.MAX_VALUE

Excepciones

El

HandlerResult devuelto por HandlerAdapter puede exponer una función para el manejo de errores basado en algún mecanismo específico del controlador. Esta función de error se llama si:

  • Falla una llamada a un controlador (por ejemplo, la anotación @Controller).

  • El procesamiento del valor de retorno del controlador a través de HandlerResultHandler falla.

La función de error puede cambiar la respuesta (por ejemplo, a el estado de error), siempre que la señal de error ocurra antes de que el tipo reactivo devuelto por el controlador produzca cualquier elemento de datos.

Métodos anotados con @ExceptionHandler en clases anotadas con @Controllerson compatibles de esta manera. Por el contrario, su soporte en Spring MVC se basa en HandlerExceptionResolver. Normalmente esto no importa. Sin embargo, tenga en cuenta que WebFlux no puede usar la anotación @ControllerAdvice para manejar excepciones que ocurren antes de que se seleccione el controlador.

Ver: Consulte también la subsección "Gestión de excepciones" en la sección "Controlador anotado" o la subsección "Excepciones" en la sección API WebHandler.

Reconocimiento de vistas

El reconocimiento de vistas permite la representación en el navegador usando plantilla y modelo HTML, sin vincularlo a una tecnología de presentación específica. En Spring WebFlux, el reconocimiento de vistas es compatible con un HandlerResultHandler especial que utiliza instancias ViewResolver para asignar una cadena (que representa el nombre lógico de la vista) a una instancia View. Luego, View se usa para representar la respuesta.

Procesamiento

El

HandlerResult se pasa al ViewResolutionResultHandler contiene el valor de retorno del controlador y un modelo que contiene los atributos agregados durante el procesamiento de la solicitud. El valor de retorno se trata como uno de los siguientes:

  • String, CharSequence: el nombre lógico de la vista que debería resolverse en View a través de una lista de implementaciones configuradas de ViewResolver.

  • void: Selecciona el nombre de la vista predeterminada según la solicitud de ruta, menos la barra diagonal inicial y final, y se resuelve en View. Lo mismo sucede si no se especificó ningún nombre de vista (por ejemplo, se devolvió un atributo de modelo) o hay un valor de retorno asincrónico (por ejemplo, Mono terminó vacío).

  • Renderizado: API para scripts de reconocimiento de vistas. Explore las capacidades de su IDE completando código.

  • Model, Map: atributos de modelo adicionales que se deben agregar a modelo para la solicitud.

  • Cualquier otro: cualquier otro valor de retorno (que no sean los tipos simples definidos por BeanUtils#isSimpleProperty) se considera un atributo del modelo que se debe agregar al modelo. El nombre del atributo se infiere del nombre de la clase usando el destino convenciones si falta la anotación del método del controlador @ModelAttribute.

El modelo puede contener tipos reactivos asíncronos (por ejemplo, de Reactor o RxJava). Antes de renderizar, AbstractView resuelve dichos atributos del modelo en valores concretos y actualiza el modelo. Los tipos reactivos de un solo valor se resuelven en un solo valor o ningún valor (si está vacío), y los tipos reactivos de múltiples valores (como Flux<T>) se recopilan y resuelven en List<T>.

Configurar el reconocimiento de vistas es tan simple como agregar el bean ViewResolutionResultHandler a su configuración de Spring. La configuración de WebFlux proporciona una API de configuración dedicada para reconocer vistas.

Redirección

El prefijo especial redirect: en el nombre de la vista permite la redirección. UrlBasedViewResolver (y subclases) reconoce esto como una indicación de que se requiere una redirección. El resto del nombre de la vista es la URL de redireccionamiento.

El resultado neto es el mismo que si el controlador hubiera devuelto RedirectView o Rendering.redirectTo("abc").build(), pero ahora el propio controlador puede operar con nombres de vistas lógicas. Un nombre de vista como redirect:/some/resource es específico de la aplicación actual, mientras que un nombre de vista como redirect:https://example.com/arbitrary/path, redirige a una URL absoluta.

Negociación de contenido

ViewResolutionResultHandler admite la negociación de contenido. Este controlador compara los tipos de medios de la solicitud con los tipos de medios admitidos por cada View seleccionada. Se utiliza la primera View que admite los tipos de medios solicitados.

Para admitir tipos de medios como JSON y XML, Spring WebFlux proporciona un HttpMessageWriterView, que es una View especial que se representa a través de un HttpMessageWriter. Normalmente, estas vistas se configuran como vistas predeterminadas a través de la configuración de WebFlux. Las vistas predeterminadas siempre se seleccionan y utilizan si coinciden con el tipo de medio solicitado.