Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the reactive programming design and working principle of Spring WebFlux

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the relevant knowledge of "Spring WebFlux reactive programming design and working principle". The editor shows you the operation process through an actual case. The operation method is simple, fast and practical. I hope this article "what is the Spring WebFlux reactive programming design and working principle" can help you solve the problem.

Preface

Spring 5 has been released for two years, and along with Spring 5 has released a Spring WebFlux at the same level as Spring WebMvc. This is a new framework that supports a reactive programming model. The biggest difference between the reactive model and the traditional MVC is asynchronous, event-driven and non-blocking, which greatly improves the concurrency performance of the application and can handle more requests per unit time. Here is not about how to use WebFlux, what is the use, there are too many such articles on the Internet, and they are all very well written. The following is mainly to see how WebFlux is built from scratch, how the framework is designed, and is expected to be able to use WebFlux more flexibly.

Interface abstraction

The best thing about Spring is that whatever it is, it can be seamlessly integrated into Spring. This is due to the excellent abstract encapsulation ability of Spring system. The same is true of the WebFlux framework, where the underlying implementation is not Spring, but relies on reactor, netty, and so on. What Spring does is to use the power of reactor through the Controller you are most familiar with through abstraction and encapsulation. And not limited to this, in addition to supporting the same controller coding mode as Spring Mvc, it also supports router mode (RouterFunctions), endpoint mode (EndPoint) and so on. In fact, all the functions of WebFlux are built from a few abstract classes:

Org.springframework.boot.web.reactive.server.ReactiveWebServerFactory

Org.springframework.boot.web.server.WebServer

Org.springframework.http.server.reactive.HttpHandler

Org.springframework.web.reactive.HandlerMapping

Org.springframework.web.server.WebHandler

WebServer

When we analyze from the bottom to the top, WebServer means the abstract class of the Reacive server, which defines the basic method behavior of the service, including start, stop and other interfaces. The structure is as follows:

Public interface WebServer {void start () throws WebServerException; void stop () throws WebServerException; int getPort ();}

By default, Spring has five implementations of WebServer. By default, without special specification, spring-boot-starter-webflux comes with an implementation of Netty. In fact, the categories are as follows:

ReactiveWebServerFactory

Corresponding to WebServer, each implementation will have a factory class, which is mainly used to create resources for WebServer instances, such as NettyReactiveWebServerFactory production WebServer method:

Public WebServer getWebServer (HttpHandler httpHandler) {HttpServer httpServer = createHttpServer (); ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter (httpHandler); return new NettyWebServer (httpServer, handlerAdapter, this.lifecycleTimeout);}

As you can see, an input parameter, HttpHandler, is passed in when the WebServer instance is created. And then passed into a HttpHandlerAdapter instance, this is because each WebServer's receive processing interface adapter is different, in each different WebServer factory through a different adapter to adapt to a different implementation. Finally, it is transformed into a unified design of HttpHandler, see below.

HttpHandler

Next, take a look at HttpHandler. When creating WebServer, an input parameter is passed, and the type is Httphandler. In order to adapt to different WebServer request response bodies, Spring designed HttpHandler to transform the underlying Http request response semantics and to receive Http requests that deal with the underlying container. Its structure is as follows:

Public interface HttpHandler {Monohandle (ServerHttpRequest request, ServerHttpResponse response);}

For example, in the implementation of Netty, the pseudocode converted in the apply of the adapter ReactorHttpHandlerAdapter that Netty receives the request for processing is as follows:

Public Monoapply (HttpServerRequest reactorRequest, HttpServerResponse reactorResponse) {NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory (reactorResponse.alloc ()); try {ReactorServerHttpRequest request = new ReactorServerHttpRequest (reactorRequest, bufferFactory); ServerHttpResponse response = new ReactorServerHttpResponse (reactorResponse, bufferFactory) If (request.getMethod () = = HttpMethod.HEAD) {response = new HttpHeadResponseDecorator (response) } return this.httpHandler.handle (request, response) .doOnError (ex-> logger.trace (request.getLogPrefix () + "Failed to complete:" + ex.getMessage ()) .doOnSuccess (aVoid-> logger.trace (request.getLogPrefix () + "Handling completed") }}

In fact, generally speaking, WebHandler is basically designed to the level of HttpHandler, with a consistent request body and response body. But Spring said it wasn't enough, it wasn't simple enough for Web development, so he created another WebHandler,WebHandler architecture that is simpler, as follows:

Public interface WebHandler {Monohandle (ServerWebExchange exchange);}

This time it is concise enough, there is only one input, so where are the request and responders? It was packaged in ServerWebExchange. Let's see what happens when HttpHandler receives the request and then calls WebHandler. The final HttpHandler implementation is HttpWebHandlerAdapter.java, which encapsulates the request and response body in ServerWebExchange through its internal createExchange method. The handle code is as follows:

Public Monohandle (ServerHttpRequest request, ServerHttpResponse response) {if (this.forwardedHeaderTransformer! = null) {request = this.forwardedHeaderTransformer.apply (request);} ServerWebExchange exchange = createExchange (request, response) LogFormatUtils.traceDebug (logger, traceOn-> exchange.getLogPrefix () + formatRequest (exchange.getRequest ()) + (traceOn? ", headers=" + formatHeaders (exchange.getRequest (). GetHeaders (): ") Return getDelegate () .handle (exchange) .doonSuccess (aVoid-> logResponse (exchange)) .onErrorResume (ex-> handleUnresolvedError (exchange, ex)) .then (Mono.defer (response::setComplete));}

HandlerMapping first looks at the construction of HandlerMapping. You can see that a Handler object is returned according to the web switch.

Public interface HandlerMapping {String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName () + ".bestMatchingHandler"; String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName () + ".bestMatchingPattern"; String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName () + ".pathWithinHandlerMapping"; String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName () + ".uriTemplateVariables" String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName () + ".matrixVariables"; String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName () + ".producibleMediaTypes"; MonogetHandler (ServerWebExchange exchange);}

The above "request" has reached WebHandler, so how does it end up with the controller interface we define? In fact, the functionality without HandlerMapping,Spring WebFlux is complete and programmable, because it can be directly coded based on WebHandler. One of our best gateways ends up going directly to the custom WebHandler. There is nothing about HandlerMapping at all, but if you do so, you will lose the friendliness of Spring coding. During the initialization of WebFlux, it goes to the Spring context to find the WebHandler implementation where name is "webHandler". By default, Spring initializes an implementation of DispatcherHandler.java in context, and the name of Bean is "webHandler". This maintains a HandlerMapping list. When the request comes, the HandlerMapping list is iterated and a WebHandler processing is returned. The code is as follows:

Public Monohandle (ServerWebExchange exchange) {if (this.handlerMappings = = null) {return Mono.error (HANDLER_NOT_FOUND_EXCEPTION) } return Flux.fromIterable (this.handlerMappings) .concatMap (mapping-> mapping.getHandler (exchange)) .next () .switchIfEmpty (Mono.error (HANDLER_NOT_FOUND_EXCEPTION)) .flatMap (handler-> invokeHandler (exchange) Handler) .flatMap (result-> handleResult (exchange, result)) }

The internal structure of the above mapping is as follows:

The arrow above explains why WebFlux supports the encoding of controller and router mode, because they have implemented HandlerMapping that can be routed to specific business methods in the handler of WebHandler. It is the interface information defined by @ Controller and @ ResultMaping in the red box.

Start process analysis

Five main abstract interface definitions, as well as functions, are introduced above. These five interfaces are soul-like beings in Spring WebFlux. However, if you want to thoroughly understand the design and implementation principle of WebFlux, it is far from enough to understand the above interface definitions. After reading the analysis of the above interface, there must be a vague sense of incomprehension, and there is no hurry. Next, analyze the startup process of Spring WebFlux in the Spring Boot environment.

ReactiveWebServerApplicationContext

The startup of WebFlux is done in the context of Reactive, similar to WebMvc, Mvc also has a ServletWebServerApplicationContext, they are of the same ancestry.

ReactiveWebServerApplicationContext also has a parent class, AnnotationConfigReactiveWebServerApplicationContext

In Spring boot startup, you create an instance of this parent class.

When you create a context in the run () method of Spring boot, you have the following code:

Protected ConfigurableApplicationContext createApplicationContext () {Class contextClass = this.applicationContextClass; if (contextClass = = null) {try {switch (this.webApplicationType) {case SERVLET: contextClass = Class.forName (DEFAULT_SERVLET_WEB_CONTEXT_CLASS) Break; case REACTIVE: contextClass = Class.forName (DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break Default: contextClass = Class.forName (DEFAULT_CONTEXT_CLASS) }} catch (ClassNotFoundException ex) {throw new IllegalStateException ("Unable create a default ApplicationContext "+" please specify an ApplicationContextClass ", ex) } return (ConfigurableApplicationContext) BeanUtils.instantiateClass (contextClass);}

As you can see, when webApplicationType is REACTIVE, DEFAULT_REACTIVE_WEB_CONTEXT_CLASS is loaded. The webApplicationType type is done by identifying which dependencies you load. Students familiar with the Spring startup process know that the basic Spring context is completed within the refresh () method of AbstractApplicationContext, and there is also an onRefresh () method for different context implementation instances to instantiate some specific Bean. For example, the context instance of WebFlux completes the creation of WebServer in onRefresh ():

Protected void onRefresh () {super.onRefresh (); try {createWebServer ();} catch (Throwable ex) {throw new ApplicationContextException ("Unable to start reactive web server", ex) }} private void createWebServer () {ServerManager serverManager = this.serverManager; if (serverManager = = null) {this.serverManager = ServerManager.get (getWebServerFactory ());} initPropertySources ();}

At the end of the article, the startup process in WebFlux is too complex, and the length of writing is too long to seriously affect the reading experience. Therefore, the upper authority should throw a brick to attract jade and make a good start. However, the start-up process node of WebFlux has been analyzed and sorted out into a flow chart. Combined with the above interface design analysis, there should be some problems in understanding the design and working principle of WebFlux.

This is the end of the content about "Spring WebFlux reactive programming design and how it works". Thank you for reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report