SpringWebFlux-1(核心学习笔记2021.11.09)

SpringWebFlux -1(5.3.12版学习笔记2021.11.09)

核心概念

1.2 反应核心

spring-web模块包含以下对反应式 Web 应用程序的基本支持:

  • 对于服务器请求处理,有两个级别的支持。
  • HttpHandler:具有非阻塞 I/O 和响应流反压力的 HTTP 请求处理的基本协定,以及 Reactor Netty,Undertow,Tomcat,Jetty 和任何 Servlet 3.1 容器的适配器。
    • WebHandler API:用于请求处理的更高级别的通用 Web API,在此之上构建了具体的编程模型,例如带 Comments 的控制器和功能端点。
  • 对于 Client 端,有一个基本的ClientHttpConnector协定,以执行具有非阻塞 I/O 和响应流反压力的 HTTP 请求,以及用于Reactor Netty和响应Jetty HtpClient的适配器。应用程序中使用的较高级别WebClient以此基本 Contract 为基础。
  • 对于 Client 端和服务器,codecs用于对 HTTP 请求和响应内容进行序列化和反序列化。

1.2.1 HttpHandler

HttpHandler是具有单个方法的简单 Contract,用于处理请求和响应。它是故意最小的,它的主要也是唯一的目的是成为对不同 HTTP 服务器 API 的最小抽象。

下表描述了受支持的服务器 API:

Server name使用的服务器 API反应式流支持
NettyNetty APIReactor Netty
UndertowUndertow APIspring-web:向响应流 bridge 过渡
TomcatServlet 3.1 非阻塞 I/O; Tomcat API 读写 ByteBuffers 与 byte []spring-web:Servlet 3.1 非阻塞 I/O 到响应流 bridge
JettyServlet 3.1 非阻塞 I/O; Jetty API 编写 ByteBuffers 与 byte []spring-web:Servlet 3.1 非阻塞 I/O 到响应流 bridge
Servlet 3.1 容器Servlet 3.1 非阻塞 I/Ospring-web:Servlet 3.1 非阻塞 I/O 到响应流 bridge

下表描述了服务器依赖性(另请参见supported versions):

Server nameGroup idArtifact name
Reactor Nettyio.projectreactor.nettyreactor-netty
Undertowio.undertowundertow-core
Tomcatorg.apache.tomcat.embedtomcat-embed-core
Jettyorg.eclipse.jettyjetty-server, jetty-servlet

下面的代码段显示了在每个服务器 API 中使用HttpHandler适配器:

Reactor Netty

HttpHandler handler = ...
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create().host(host).port(port).handle(adapter).bind().block();

Undertow

HttpHandler handler = ...
UndertowHttpHandlerAdapter adapter = new UndertowHttpHandlerAdapter(handler);
Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build();
server.start();

Tomcat

HttpHandler handler = ...
Servlet servlet = new TomcatHttpHandlerAdapter(handler);

Tomcat server = new Tomcat();
File base = new File(System.getProperty("java.io.tmpdir"));
Context rootContext = server.addContext("", base.getAbsolutePath());
Tomcat.addServlet(rootContext, "main", servlet);
rootContext.addServletMappingDecoded("/", "main");
server.setHost(host);
server.setPort(port);
server.start();

Jetty

HttpHandler handler = ...
Servlet servlet = new JettyHttpHandlerAdapter(handler);

Server server = new Server();
ServletContextHandler contextHandler = new ServletContextHandler(server, "");
contextHandler.addServlet(new ServletHolder(servlet), "/");
contextHandler.start();

ServerConnector connector = new ServerConnector(server);
connector.setHost(host);
connector.setPort(port);
server.addConnector(connector);
server.start();

Servlet 3.1 容器

要作为 WAR 部署到任何 Servlet 3.1 容器,您可以扩展AbstractReactiveWebInitializer并将其包含在 WAR 中。该类用ServletHttpHandlerAdapter包装HttpHandler并将其注册为Servlet

1.2.2 WebHandler API

org.springframework.web.server包构建在HttpHandlerContracts 的基础上,以提供通用 Web API,以通过多个WebExceptionHandler,多个WebFilter和单个WebHandler组件链处理请求。可以通过简单地指向组件为auto-detected的 Spring ApplicationContext和/或通过向构建器注册组件来将链与WebHttpHandlerBuilder放在一起。

HttpHandler的抽象目标很简单,而WebHandler API 的目的是提供 Web 应用程序中常用的更广泛的功能集,例如:

  • 具有属性的用户会话。
  • Request attributes.
  • 解决了LocalePrincipal的请求。
  • 访问已解析和缓存的表单数据。
  • Multipart 数据的抽象。
  • and more…
特殊 bean 类型

下表列出了WebHttpHandlerBuilder可以在 Spring ApplicationContext 中自动检测的组件,或者可以直接向其注册的组件:

Bean nameBean typeCountDescription
WebExceptionHandler0…N提供对来自WebFilter实例链和目标WebHandler的异常的处理。有关更多详细信息,请参见Exceptions
WebFilter0…N在其余的过滤链和目标WebHandler之前和之后应用拦截样式逻辑。有关更多详细信息,请参见Filters
webHandlerWebHandler1请求的处理程序。
webSessionManagerWebSessionManager0…1通过ServerWebExchange上的方法公开的WebSession个实例的 Management 器。 DefaultWebSessionManager默认情况下。
serverCodecConfigurerServerCodecConfigurer0…1用于访问HttpMessageReader实例以解析表单数据和 Multipart 数据,然后通过ServerWebExchange上的方法公开这些数据。 ServerCodecConfigurer.create()默认情况下。
localeContextResolverLocaleContextResolver0…1LocaleContext的解析器通过ServerWebExchange上的方法公开。 AcceptHeaderLocaleContextResolver默认情况下。
forwardedHeaderTransformerForwardedHeaderTransformer0…1对于处理转发的类型 Headers,可以通过提取和删除它们或仅通过删除它们来进行。默认不使用。
Form Data (表单数据)

ServerWebExchange公开了以下访问表单数据的方法:

Mono<MultiValueMap<String, String>> getFormData();

DefaultServerWebExchange使用配置的HttpMessageReader将表单数据(application/x-www-form-urlencoded)解析为MultiValueMap。缺省情况下,FormHttpMessageReader配置为由ServerCodecConfigurer bean 使用(请参见Web 处理程序 API)。

Multipart Data (多部分数据(文件))

与 Spring MVC 中的相同

ServerWebExchange公开了以下访问 Multipart 数据的方法:

Mono<MultiValueMap<String, Part>> getMultipartData();

DefaultServerWebExchange使用配置的HttpMessageReader<MultiValueMap<String, Part>>multipart/form-data内容解析为MultiValueMap。目前,Synchronoss NIOMultipart是唯一受支持的第三方库,也是我们知道的用于非阻塞解析 Multipart 请求的唯一库。通过ServerCodecConfigurer bean(请参阅Web 处理程序 API)启用了它。

要以流方式解析 Multipart 数据,可以改用HttpMessageReader<Part>返回的Flux<Part>。例如,在带 Comments 的控制器中,使用@RequestPart意味着按名称对单个部分进行Map类访问,因此需要完整地解析 Multipart 数据。相反,您可以使用@RequestBody将内容解码为Flux<Part>而不收集为MultiValueMap

Forwarded Headers (转发)

与 Spring MVC 中的相同

当请求通过代理(例如负载平衡器)进行处理时,主机,端口和方案可能会更改,从 Client 端的角度来看,要创建指向正确的主机,端口和方案的链接是一个挑战。

RFC 7239定义Forwarded HTTPHeaders,代理可用来提供有关原始请求的信息。还有其他非标准 Headers,包括X-Forwarded-HostX-Forwarded-PortX-Forwarded-ProtoX-Forwarded-SslX-Forwarded-Prefix

ForwardedHeaderTransformer是一个组件,可根据转发的 Headers 修改请求的主机,端口和方案,然后删除这些 Headers。您可以将其声明为名称为forwardedHeaderTransformer的 bean,并且它是detected并且已使用。

对于转发的 Headers,存在安全方面的考虑,因为应用程序无法知道 Headers 是由代理添加的,还是由恶意 Client 端添加的。这就是为什么应配置信任边界处的代理以删除来自外部的不受信任的转发流量的原因。您也可以使用removeOnly=true配置ForwardedHeaderTransformer,在这种情况下,它会删除但不使用标题。

1.2.3 Filters (过滤器)

与 Spring MVC 中的相同

WebHandler API中,您可以使用WebFilter在其余过滤器处理链和目标WebHandler之前和之后应用拦截样式的逻辑。使用WebFlux Config时,注册WebFilter就像将其声明为 Spring bean 一样简单,并且(可选)通过在 bean 声明上使用@Order或实现Ordered来表达优先级。

CORS (跨域)

与 Spring MVC 中的相同

Spring WebFlux 通过控制器上的 Comments 为 CORS 配置提供了细粒度的支持。但是,当您将其与 Spring Security 结合使用时,我们建议您依赖内置的CorsFilter,该参数必须在 Spring Security 的过滤器链之前 Order。

有关更多详细信息,请参见CORSCORS WebFilter部分。

1.2.4 Exceptions (异常)

与 Spring MVC 中的相同

WebHandler API中,可以使用WebExceptionHandler来处理WebFilter实例链和目标WebHandler链中的异常。使用WebFlux Config时,注册WebExceptionHandler就像将其声明为 Spring bean 一样简单,并且(可选)通过在 bean 声明上使用@Order或实现Ordered来表达优先级。

下表描述了可用的WebExceptionHandler实现: 该处理程序在WebFlux Config中声明。

Exception HandlerDescription
ResponseStatusExceptionHandler通过将响应设置为异常的 HTTP 状态代码,提供对ResponseStatusException类型的异常的处理。
WebFluxResponseStatusExceptionHandlerResponseStatusExceptionHandlerextensions,也可以确定任何异常上的@ResponseStatus注解的 HTTP 状态代码。

1.2.5 Codecs (编解码器)

与 Spring MVC 中的相同

spring-webspring-core模块提供了对通过非阻塞 I/O(具有 Reactive Streams 背压)在高级对象之间来回串行化和反序列化字节内容的支持。以下介绍了此支持:

  • EncoderDecoder是底层协议,用于独立于 HTTP 编码和解码内容。
  • HttpMessageReaderHttpMessageWriter是对 HTTP 消息内容进行编码和解码的协定。
  • Encoder可以用EncoderHttpMessageWriter包裹以使其适合在 Web 应用程序中使用,而Decoder可以用DecoderHttpMessageReader包裹。
  • DataBuffer提取不同的字节缓冲区表示形式(例如 Netty ByteBufjava.nio.ByteBuffer等),并且是所有编解码器都在处理的内容。有关此主题的更多信息,请参见“ Spring Core”部分中的数据缓冲区和编解码器

spring-core模块提供byte[]ByteBufferDataBufferResourceString编码器和解码器实现。 spring-web模块提供 Jackson JSON,Jackson Smile,JAXB2,Protocol Buffers 和其他编码器和解码器,以及用于表单数据,Multipart 内容,服务器发送的事件以及其他内容的纯 Web HTTP 消息读取器和写入器实现。

ClientCodecConfigurerServerCodecConfigurer通常用于配置和自定义要在应用程序中使用的编解码器。请参阅有关配置HTTP 消息编解码器的部分。

Jackson JSON

存在 Jackson 库时,都支持 JSON 和二进制 JSON(Smile)。

Jackson2Decoder的工作方式如下:

  • Jackson 的异步,非阻塞解析器用于将字节块流聚合到TokenBuffer,每个_代表一个 JSON 对象。
  • 每个TokenBuffer都传递给 Jackson 的ObjectMapper以创建更高级别的对象。
  • 解码为单值发布者(例如Mono)时,有一个TokenBuffer
  • 当解码为多值发布者(例如Flux)时,只要为完整格式的对象接收到足够的字节,每个TokenBuffer就会传递给ObjectMapper。Importing 的内容可以是 JSON 数组,如果 Content Type 为“ application/stream json”,则为line-delimited JSON

Jackson2Encoder的工作方式如下:

  • 对于单个价值发布者(例如Mono),只需通过ObjectMapper对其进行序列化即可。
  • 对于具有“ application/json”的多值发布者,默认情况下使用Flux#collectToList()收集值,然后序列化结果集合。
  • 对于具有流媒体类型(例如application/stream+jsonapplication/stream+x-jackson-smile)的多值发布者,请使用line-delimited JSON格式分别对每个值进行编码,写入和刷新。
  • 对于 SSE,每个事件都调用Jackson2Encoder,并且刷新输出以确保传递时没有延迟。

默认情况下,Jackson2EncoderJackson2Decoder都不支持String类型的元素。相反,默认假设是一个字符串或一系列字符串表示要由CharSequenceEncoder呈现的序列化 JSON 内容。如果您需要从Flux<String>渲染 JSON 数组,请使用Flux#collectToList()并编码Mono<List<String>>

Form Data

FormHttpMessageReaderFormHttpMessageWriter支持对“ application/x-www-form-urlencoded”内容进行解码和编码。

在经常需要从多个位置访问表单内容的服务器端,ServerWebExchange提供了专用的getFormData()方法,该方法通过FormHttpMessageReader解析内容,然后缓存结果以进行重复访问。请参阅WebHandler API部分中的Form Data

使用getFormData()后,将无法再从请求正文中读取原始原始内容。因此,与从原始请求主体读取数据相比,应用程序应始终通过ServerWebExchange访问缓存的表单数据。

Multipart

MultipartHttpMessageReaderMultipartHttpMessageWriter支持对“Multipart/表单数据”内容进行解码和编码。依次将MultipartHttpMessageReader委派给另一个HttpMessageReader以便实际解析为Flux<Part>,然后将这些部分简单地收集到MultiValueMap中。目前,Synchronoss NIOMultipart用于实际解析。

在可能需要从多个位置访问 Multipart 表单内容的服务器端,ServerWebExchange提供了专用的getMultipartData()方法,该方法通过MultipartHttpMessageReader解析内容,然后缓存结果以进行重复访问。请参阅WebHandler API部分中的Multipart Data

使用getMultipartData()后,将无法再从请求正文中读取原始原始内容。因此,应用程序必须始终使用getMultipartData()来重复,类似 Map 地访问 Component,否则必须依靠SynchronossPartHttpMessageReader来一次性访问Flux<Part>

Limits

DecoderHttpMessageReader该缓冲区一些或所有输入流的实施方式中可以与字节在内存中缓冲的最大数量的限制来配置。在某些情况下,会发生缓冲是因为输入被聚合并表示为单个对象——例如,带有@RequestBody byte[]x-www-form-urlencoded数据等的控制器方法。在拆分输入流时,流式传输也可能发生缓冲 — 例如,分隔文本、JSON 对象流等。对于那些流情况,限制适用于与流中的一个对象关联的字节数。

要配置缓冲区大小,您可以检查给定的DecoderHttpMessageReader 公开的maxInMemorySize属性,如果是,Javadoc 将提供有关默认值的详细信息。在服务器端,ServerCodecConfigurer提供设置所有编解码器的单一位置,请参阅HTTP 消息编解码器。在客户端,可以在WebClient.Builder 中更改所有编解码器的限制 。

对于多部分解析,maxInMemorySize属性限制了非文件部分的大小。对于文件部分,它确定将部分写入磁盘的阈值。对于写入磁盘的文件部分,还有一个附加 maxDiskUsagePerPart属性来限制每个部分的磁盘空间量。还有一个maxParts属性可以限制多部分请求中的部分总数。要配置所有三个WebFlux,你需要提供的预先配置的实例 MultipartHttpMessageReaderServerCodecConfigurer

Streaming

与 Spring MVC 中的相同

在流式传输到 HTTP 响应(例如text/event-streamapplication/stream+json)时,定期发送数据很重要,以便尽早而不是稍后可靠地检测到断开连接的 Client 端。这样的发送可以是仅 Comments 的空 SSE 事件,也可以是有效用作心跳的任何其他“无操作”数据。

DataBuffer

DataBuffer是 WebFlux 中字节缓冲区的表示形式。参考的 Spring Core 部分在数据缓冲区和编解码器的部分中有更多内容。要理解的关键点是,在诸如 Netty 之类的某些服务器上,字节缓冲区被池化并引用计数,并且在消耗字节缓冲区时必须将其释放以避免内存泄漏。

WebFlux 应用程序通常无需关心此类问题,除非它们直接使用或产生数据缓冲区,而不是依赖于编解码器与更高级别的对象进行转换。或者,除非他们选择创建自定义编解码器。对于这种情况,请查看数据缓冲区和编解码器中的信息,尤其是Using DataBuffer部分。

自定义编解码器

应用程序可以注册自定义编解码器以支持其他媒体类型或默认编解码器不支持的特定行为。

开发人员表达的一些配置选项在默认编解码器上强制执行。自定义编解码器可能希望有机会与这些首选项保持一致,例如强制执行缓冲限制记录敏感数据

以下示例显示了如何对客户端请求执行此操作:

WebClient webClient = WebClient.builder()
        .codecs(configurer -> {
                CustomDecoder decoder = new CustomDecoder();
                configurer.customCodecs().registerWithDefaultConfig(decoder);
        })
        .build();

1.2.6 Logging (日志)

与 Spring MVC 中的相同

Spring WebFlux 中的 DEBUG 级别日志记录旨在紧凑,最小化并且对用户友好。它侧重于一遍又一遍有用的高价值信息,而其他信息则仅在调试特定问题时才有用。

TRACE 级别的日志记录通常遵循与 DEBUG 相同的原理(例如,也不应成为 firehose),但可用于调试任何问题。此外,某些日志消息在 TRACE vs DEBUG 上可能显示不同级别的详细信息。

良好的日志记录来自使用日志的经验。

Log Id

在 WebFlux 中,单个请求可以在多个线程上执行,并且线程 ID 对于关联属于特定请求的日志消息没有用。这就是为什么 WebFlux 日志消息默认情况下带有特定于请求的 ID 的原因。

在服务器端,日志 ID 存储在ServerWebExchange属性(LOG_ID_ATTRIBUTE)中,而ServerWebExchange#getLogPrefix()提供了基于该 ID 的完全格式化的前缀。在WebClient端,日志 ID 存储在ClientRequest属性(LOG_ID_ATTRIBUTE)中,而ClientRequest#logPrefix()提供了完整格式的前缀。

Sensitive Data (敏感数据)

与 Spring MVC 中的相同

DEBUGTRACE日志记录可以记录敏感信息。这就是默认情况下屏蔽表单参数和标题的原因,并且必须显式启用它们的完整日志记录。

以下示例显示了如何针对服务器端请求执行此操作:

@Configuration
@EnableWebFlux
class MyConfig implements WebFluxConfigurer {

    @Override
    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
        configurer.defaultCodecs().enableLoggingRequestDetails(true);
    }
}

以下示例显示了如何针对 Client 端请求执行此操作:

Consumer<ClientCodecConfigurer> consumer = configurer ->
        configurer.defaultCodecs().enableLoggingRequestDetails(true);

WebClient webClient = WebClient.builder()
        .exchangeStrategies(ExchangeStrategies.builder().codecs(consumer).build())
        .build();

诸如 SLF4J 和 Log4J 2 之类的日志记录库提供了避免阻塞的异步记录器。虽然这些都有自己的缺点,例如可能会丢弃无法排队等待日志记录的消息,但它们是当前用于响应式、非阻塞应用程序的最佳可用选项。

1.3 DispatcherHandler

与 Spring MVC 中的相同

与 Spring MVC 类似,Spring WebFlux 围绕前端控制器模式进行设计,其中中央WebHandlerDispatcherHandler提供了用于请求处理的共享算法,而实际工作是由可配置的委托组件执行的。该模型非常灵活,并支持多种工作流程。

DispatcherHandler从 Spring 配置中发现所需的委托组件。它还被设计为 Spring Bean 本身,并实现ApplicationContextAware以访问其运行的上下文。如果以webHandler的 bean 名称声明了DispatcherHandler,则依次由WebHttpHandlerBuilder发现,该_组合了一个请求处理链,如WebHandler API中所述。

WebFlux 应用程序中的 Spring 配置通常包含:

配置已分配给WebHttpHandlerBuilder以构建处理链,如以下示例所示:

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

生成的HttpHandler准备与server adapter一起使用。

特殊 bean 类

与 Spring MVC 中的相同

DispatcherHandler委托特殊 bean 处理请求并呈现适当的响应。所谓“特殊 bean”,是指实现 WebFlux 框架 Contract 的 SpringManagement 的Object实例。这些通常带有内置 Contract,但是您可以自定义它们的属性,扩展它们或替换它们。

下表列出了DispatcherHandler. 请注意,在较低级别还检测到一些其他 bean(请参阅 Web Handler API 中的特殊 bean 类型)。

Bean type解释
HandlerMapping将请求映射到处理程序。映射基于一些标准,其细节因HandlerMapping实现而异——带注释的控制器、简单的 URL 模式映射等。主要HandlerMapping实现RequestMappingHandlerMapping用于带 @RequestMapping注释的方法、RouterFunctionMapping功能端点路由以及SimpleUrlHandlerMappingURI 路径模式和WebHandler实例的显式注册。
HandlerAdapter帮助DispatcherHandler调用映射到请求的处理程序,而不管处理程序实际是如何调用的。例如,调用带注释的控制器需要解析注释。a 的主要目的HandlerAdapter是屏蔽 DispatcherHandler这些细节。
HandlerResultHandler处理处理程序调用的结果并最终确定响应。请参阅结果处理
WebFlux 配置

与 Spring MVC 中的相同

应用程序可以声明处理请求所需的基础结构 bean(在Web 处理程序 APIDispatcherHandler下列出)。但是,在大多数情况下,WebFlux Config是最佳起点。它声明了所需的 bean,并提供了更高级别的配置回调 API 来对其进行自定义。

Spring Boot 依靠 WebFlux 配置来配置 Spring WebFlux,并且还提供了许多额外的方便选项。

Processing

与 Spring MVC 中的相同

DispatcherHandler处理请求的方式如下:

  • 要求每个HandlerMapping查找匹配的处理程序,并使用第一个匹配项。
  • 如果找到处理程序,则通过适当的HandlerAdapter执行该处理程序,该处理程序将执行返回的值公开为HandlerResult
  • 通过直接写入响应或使用视图进行渲染,将HandlerResult赋予适当的HandlerResultHandler以完成处理。
结果处理

通过HandlerAdapter调用处理程序的返回值与HandlerResult一起包装为HandlerResult,并附加到其他上下文中,并传递给要求支持它的第一个HandlerResultHandler。下表显示了可用的HandlerResultHandler实现,所有实现均在WebFlux Config中声明:

结果处理程序类型Return ValuesDefault Order
ResponseEntityResultHandlerResponseEntity,通常来自@Controller个实例。0
ServerResponseResultHandlerServerResponse,通常来自功能端点。0
ResponseBodyResultHandler处理来自@ResponseBody个方法或@RestController个类的返回值。100
ViewResolutionResultHandlerCharSequenceViewModelMapRendering或任何其他Object被视为模型属性。 另请参见View Resolution。 ``Integer.MAX_VALUE
Exceptions

与 Spring MVC 中的相同

HandlerAdapter返回的HandlerResult可以公开基于某些特定于处理程序的机制进行错误处理的函数。在以下情况下将调用此错误函数:

  • 处理程序(例如@Controller)调用失败。
  • 通过HandlerResultHandler处理处理程序返回值失败。

只要在从处理程序返回的反应类型产生任何数据项之前发生错误 signal,错误函数就可以更改响应(例如,更改为错误状态)。

这就是支持@Controller类中的@ExceptionHandler方法的方式。相比之下,Spring MVC 中对HandlerExceptionResolver的支持基于此。这通常不重要。但是,请记住,在 WebFlux 中,不能使用@ControllerAdvice处理在(控制层)选择处理程序之前发生的异常。

另请参见“带 Comments 的控制器”部分中的Managing Exceptions或 WebHandler API 部分中的Exceptions

查看视图

与 Spring MVC 中的相同

视图分辨率使您可以使用 HTML 模板和模型渲染到浏览器,而无需将您与特定的视图技术联系在一起。在 Spring WebFlux 中,通过使用ViewResolver实例将 String(代表逻辑视图名称)Map 到View实例的专用HandlerResultHandler支持视图解析。 View然后用于呈现响应。

Handling

与 Spring MVC 中的相同

传递给ViewResolutionResultHandlerHandlerResult包含处理程序的返回值和包含请求处理过程中添加的属性的模型。返回值将作为以下值之一进行处理:

  • StringCharSequence:通过已配置的ViewResolver实现的列表解析为View的逻辑视图名称。
  • void:根据请求路径选择默认视图名称,减去前斜杠和后斜杠,然后将其解析为View。当未提供视图名称(例如,返回了模型属性)或异步返回值(例如,Mono已完成为空)时,也会发生同样的情况。
  • Rendering:用于视图分辨率方案的 API。通过代码完成探索 IDE 中的选项。
  • ModelMap:要添加到请求模型的额外模型属性。
  • 任何其他:任何其他返回值(由BeanUtils#isSimpleProperty确定的简单类型除外)都将被视为要添加到模型的模型属性。除非存在处理程序方法@ModelAttribute注解,否则使用conventions从类名称派生属性名称。

该模型可以包含异步,反应式类型(例如,来自 Reactor 或 RxJava)。在渲染之前,AbstractView将此类模型属性解析为具体值并更新模型。单值反应类型被解析为单个值或无值(如果为空),而多值反应类型(例如Flux<T>)被收集并解析为List<T>

配置视图分辨率就像在 Spring 配置中添加ViewResolutionResultHandler bean 一样简单。 WebFlux Config提供用于视图分辨率的专用配置 API。

有关与 Spring WebFlux 集成的视图技术的更多信息,请参见View Technologies

Redirecting

与 Spring MVC 中的相同

视图名称中特殊的redirect:前缀使您可以执行重定向。 UrlBasedViewResolver(及其子类)将其识别为需要重定向的指令。视图名称的其余部分是重定向 URL。

最终效果与控制器返回RedirectViewRendering.redirectTo("abc").build()的效果相同,但是现在控制器本身可以根据逻辑视图名称进行操作。诸如redirect:/some/resource之类的视图名称是相对于当前应用程序的,而诸如redirect:http://example.com/arbitrary/path之类的视图名称则重定向到绝对 URL。

Content Negotiation

与 Spring MVC 中的相同

ViewResolutionResultHandler支持内容协商。它将请求媒体类型与每个选定的View支持的媒体类型进行比较。使用支持请求的媒体类型的第一个View

为了支持 JSON 和 XML 之类的媒体类型,Spring WebFlux 提供了HttpMessageWriterView,这是一个特殊的View,它通过HttpMessageWriter呈现。通常,您可以通过WebFlux Configuration将它们配置为默认视图。如果默认视图与请求的媒体类型匹配,则始终会选择和使用它们。

1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懵懵懂懂程序员

如果节省了你的时间, 请鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值