当前位置: 首页 > 科技观察

SpringWebFlux核心组件详解

时间:2023-03-20 15:05:58 科技观察

环境:Springboot2.4.12概述spring-web模块包括以下对响应式Web应用的基本支持:对于服务器请求处理,有两级支持。HttpHandler:处理HTTP请求的基本协议,包括非阻塞I/O和反应流背压,以及ReactorNetty、Undertow、Tomcat、Jetty和任何Servlet3.1+容器的适配器。WebHandlerAPI:一种稍微更高级的通用WebAPI,用于处理请求,在其上构建了特定的编程模型,例如带注释的控制器和功能端点。对于客户端,有一个基本的ClientHttpConnector合约来执行HTTP请求,包括非阻塞I/O和反应流背压,以及ReactorNetty、ReactiveJettyHttpClient和ApacheHttpComponents的适配器。应用程序中使用的高级Web客户端构建在这个基本契约之上。用于客户端和服务器的HTTP请求和响应内容的序列化和反序列化的编解码器。HttpHandlerHttpHandler是一个简单的协议,只有一种方法来处理请求和响应。它是有意最小化的,其主要和唯一目的是提供对不同HTTP服务器API的最小化抽象。支持的服务端API如下表所示:服务端服务APIreactivestreams支持NettyNettyAPIReactorNettyUndertowUndertowAPIspring-web:UndertowtoReactiveStreamsbridgeTomcatServlet3.1non-blockingI/O;TomcatAPI读写ByteBuffersvsbyte[]spring-web:Servlet3.1非阻塞I/O到ReactiveStreams桥接JettyServlet3.1非阻塞I/O;JettyAPI编写ByteBuffersvsbyte[]spring-web:Servlet3.1非阻塞I/O到ReactiveStreams桥接Servlet3.1containerServlet3.1非阻塞I/Ospring-web:Servlet3.1Non-blockingI/OtoReactiveStreamsbridge下表描述了服务器依赖项:服务器组idArtifactnameReactorNettyio.projectreactor.nettyreactor-nettyUndertowio.undertowundertow-coreTomcatorg.apache.tomcat.embedtomcat-embed-coreJettyorg.eclipse.jettyjetty-server,jetty-servlet以下片段显示了使用每个服务器API中的HttpHandler适配器:ReactorNettyHttpHandlerhandler=WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();ReactorHttpHandlerAdapteradapter=newReactorHttpHandlerAdapter(handler);HttpServer.create().host(host).port(port)。句柄(适配r).bind().block();UndertowHttpHandlerhandler=WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();UndertowHttpHandlerAdapteradapter=newUndertowHttpHandlerAdapter(handler);Undertowserver=Undertow.builder().addHttpListener(port,host).setHandler(adapter).build();server.start();TomcatHttpHandlerhandler=WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();Servletservlet=newTomcatHttpHandlerAdapter(handler);Tomcatserver=newTomcat();Filebase=newFile(System.getProperty("java.io.tmpdir"));ContextrootContext=server.addContext("",base.getAbsolutePath());Tomcat.addServlet(rootContext,"main",servlet);rootContext.addServletMappingDecoded("/","main");server.setHost(host);server.setPort(port);server.start();JettyHttpHandlerhandler=WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();Servletservlet=newJettyHttpHandlerAdapter(handler);Serverserver=newServer();ServletContextHandlercontextHandler=newServletContextHandler(server,"");contextHandler.addServlet(newServletHolder(servlet),"/");contextHandler.start();ServerConnectorconnector=newServerConnector(server);connector.setHost(host);connector.setPort(port);server.addConnector(connector);server.start();Servlet3.1+Container要将war部署到任何Servlet3.1+容器,您可以在war中扩展并包含AbstractReactiveWebInitializer这个类用ServletHttpHandlerAdapter包装一个HttpHandler,并将其注册为一个Servlet。部分源码:publicabstractclassAbstractReactiveWebInitializerimplementsWebApplicationInitializer{publicvoidonStartup(ServletContextservletContext)throwsServletException{StringservletName=getServletName();ApplicationContextapplicationContext=createApplicationContext();refreshApplicationContext(applicationContext);registerCloseListener(servletContext,applicationContext);//与上面的服务器同样通过WebHttpHandlerBuilder构建HttpHandler对象HttpHandlerhttpHandler=WebHttpHandlerBuilder.applicationContext(applicationContext).build();//这个类实现了javax.servlet.Servlet接口ServletHttpHandlerAdapterservlet=newServletHttpHandlerAdapter(httpConletDynistregistler);ServletRegist.addServlet(servletName,servlet);注册.setLoadOnStartup(1);registration.addMapping(getServletMapping());registration.setAsyncSupported(true);WebHandlerorg.springframework.web.server包构建在HttpHandler契约之上,通过多个WebExceptionHandler链、多个WebFilters和单个WebHandler组件提供一个通用的WebAPI来处理请求。只需指向自动检测组件的SpringApplicationContext,或向构建器注册组件以将链与WebHttpHandlerBuilder结合起来。HttpHandler的目标只是简单地抽象出不同的HTTP服务器,而WebHandlerAPI的目标是提供更广泛的Web应用程序中常用的功能,例如:用户会话请求属性以及解析请求的区域设置或正文访问的属性已解析和缓存的表单数据多部分数据的摘要。等等特殊bean类型下表列出了WebHttpHandlerBuilder可以自动检测或直接在SpringApplicationContext中注册的组件:在目标WebHandler之后。webHandlerWebHandler1请求处理程序。webSessionManagerWebSessionManager0..1通过ServerWebExchange上的方法公开的WebSession实例管理器。默认为DefaultWebSessionManager。serverCodecConfigurerServerCodecConfigurer0..1用于访问HttpMessageReader实例,解析表单数据和multipart数据,然后通过ServerWebExchange上的方法暴露这些数据。默认情况下它是servercodecconfiguration.create()。localeContextResolverLocaleContextResolver0..1LocaleContext的解析器通过ServerWebExchange上的方法公开。默认为AcceptHeaderLocaleContextResolver。forwardedHeaderTransformerForwardedHeaderTransformer0..1用于处理转发的类型标头,提取并删除它们,或者只是删除它们。默认不使用。FormDataServerWebExchange公开了以下方法来访问表单数据:Mono>getFormData();DefaultServerWebExchange使用已配置的HttpMessageReader将表单数据(application/x-www-form-urlencoded)解析为MultiValueMap。默认情况下,FormHttpMessageReader配置为由ServerCodecConfigurerbean使用。MultipartDataServerWebExchange公开了以下方法来访问多部分数据:Mono>getMultipartData();DefaultServerWebExchange使用配置的HttpMessageReader>将多部分/表单数据内容解析为MultiValueMap。默认情况下,这是DefaultPartHttpMessageReader,它没有任何第三方依赖项。或者,也可以使用基于SynchronossnioMultipart库的SynchronossPartHttpMessageReader。两者都是通过ServerCodecConfigurerbean配置的。要以流方式解析多部分数据,您可以使用HttpMessageReader返回的`Flux`。例如,在带注释的控制器中,使用@RequestPart意味着按名称访问部件,如地图,因此需要对多个部件的数据进行完整解析。相比之下,@RequestBody可用于将内容解码为Flux而无需收集到MultiValueMap中。过滤器在WebHandlerAPI中,您可以使用WebFilter在过滤器和目标WebHandler的其余处理链前后应用拦截式逻辑。使用WebFlux配置时,注册WebFilter就像将其声明为Springbean一样简单,并且(可选)通过使用@Order或在bean声明上实现Ordered来表达优先级。异常在WebHandlerAPI中,WebExceptionHandler可用于处理来自WebFilter实例链和目标WebHandler的异常。使用WebFlux配置时,注册WebExceptionHandler就像将其声明为Springbean一样简单,并且(可选)通过使用@Order或在bean声明上实现Ordered来表达优先级。下表描述了可用的WebExceptionHandler实现:ExceptionHandlerDescriptionResponseStatusExceptionHandler通过设置对异常的HTTP状态代码的响应来处理ResponseStatusException类型的异常。WebFluxResponseStatusExceptionHandler扩展了ResponseStatusExceptionHandler,它还可以确定任何异常的@ResponseStatus注释的HTTP状态代码。此处理程序在WebFlux配置中声明。编解码器spring-web和spring-core模块通过非阻塞I/O提供反应流背压,支持字节内容与高级对象之间的序列化和反序列化。下面介绍这种支持:Encoder和Decoder是独立于HTTP对内容进行编码和解码的底层协议。HttpMessageReader和HttpMessageWriter是编码和解码HTTP消息内容的协议。Encoder可以用EncoderHttpMessageWriter包装用于Web应用程序,Decoder可以用DecoderHttpMessageReader包装。DataBuffer抽象出不同的字节缓冲区表示(例如NettyByteBuf、java.nio.ByteBuffer等),所有编解码器都可以处理。spring-core模块提供byte[]、ByteBuffer、DataBuffer、Resource和String编码器和解码器的实现。spring-web模块提供了JacksonJSON、JacksonSmile、JAXB2、Protocolbuffer和其他编码器和解码器,以及用于表单数据、多部分内容、服务器发送事件等的仅webHTTP消息读取器和写入器实现。