This is the 9th day of my participation in the August More Text Challenge. For details, see:August is more challenging
WebFlux is an asynchronous and non-blocking Web Framework based on Reactor released by Spring Framework 5.0. Using WebFlux can make full use of the multi-core advantage of computing to improve the throughput and scalability of the system.
WebFlux does not reduce the response time of the interface, it only improves throughput and scalability
The following figure shows a comparison of Spring WebFlux and Spring MVC applications
- Run the container
Spring WebFlux: Can run in Netty, Undertow and Servlet 3.1 containers and above. Spring MVC: can run in Servlet 3.1 containers
- API for container and application interaction
Spring WebFlux: Uses the Reactor Stream Adapters Spring MVC: uses the Servlet API
- security
Spring WebFlux: Uses Spring Security Reactor. Spring MVC: Uses synchronization Security frameworks such as Spring Security
- Data is stored
Spring WebFlux: Use Spring Data Reactor Repositories to interact with databases, supporting Spring MVC (Mongo, Cassandra, Redis, CouchBase, R2DBC) : Use Spring Data Repositories to interact with the database
There are two ways to use WebFlux: Annotated Controllers and Functional Endpoints
- Annotation: and
SpringMvc
The annotation is consistent with that usedRestController
,GetMapping
,PostMapping
Such as annotation - Functional: Based on Lambda expressions, using
Function
Describe request endpoints
Annotation type (Annotated Controllers)
Spring Validation is supported using the RestController, GetMapping, and PostMapping annotations, consistent with SpringMvc annotations
Functional (Functional Endpoints)
The functional version of WebFlux uses Router and Handler to handle requests. The RouterFunction receives the HTTP request and finds the corresponding HandlerFunction. The HandlerFunction processes the HTTP request and returns a delayed ServerResponse
HandlerFunction
The HandlerFunction handles requests and responses using ServerRequest and ServerResponse
ServerRequest
ServerRequest provides method, URI, HEADERS, and Query parameters for accessing HTTP requests
// Obtain the requested method
HttpMethod method = serverRequest.method();
// Get the request URI
URI uri = serverRequest.uri();
// Obtain the headers of the request
ServerRequest.Headers headers = serverRequest.headers();
// Get the query parameters with the specified key
Optional<String> id = serverRequest.queryParam("id");
// Obtain all query parameters for the request
MultiValueMap<String, String> stringStringMultiValueMap = serverRequest.queryParams();
// Obtain the request path
RequestPath requestPath = serverRequest.requestPath();
Copy the code
Extract the request body and convert it to Mono or Flux
// Get the request body and convert it to Mono
Mono<String> string = serverRequest.bodyToMono(String.class);
// Get the request body and convert it to Flux
Flux<Person> people = serverRequest.bodyToFlux(User.class);
Mono<String> string = serverRequest.body(BodyExtractors.toMono(String.class));
Flux<Person> people = serverRequest.body(BodyExtractors.toFlux(User.class));
// Retrieve the formData data
Mono<MultiValueMap<String, String>> map = serverRequest.formData();
// Get the multipartData data
Mono<MultiValueMap<String, Part>> map1 = serverRequest.multipartData();
// Obtain request body data and convert it to Flux
Flux<Part> parts = serverRequest.body(BodyExtractors.toParts());
Copy the code
ServerResponse
ServerResponse can access the Response of an HTTP request. You can use builder mode to set the Response status, Response header, and Response body
User user = User.builder()
.id(1)
.name("Zhang")
.age(18)
.build();
return ServerResponse.ok().body(user, User.class);
Copy the code
Construct using Lambda expressionsHandlerFunction
HandlerFunction<ServerResponse> helloWorld = request -> ServerResponse.ok().bodyValue("Hello World");
Copy the code
RouterFunction
The RouterFunction is responsible for finding the corresponding HandlerFunction for processing the request
RouterFunction<ServerResponse> route = RouterFunctions.route()
.GET("/person/{id}",, handler::getPerson)
.POST("/person", handler::createPerson)
.build();
Copy the code
RequestPredicate (RequestPredicate)
Methods like GET, POST, and so on have overloaded methods that accept request assertion parameters. If the request method and path match,RequestPredicate returning true will be processed by the corresponding HandlerFunction
RouterFunction<ServerResponse> route = route()
// Accept limits the type of the request to JSON
.GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson)
.POST("/person", handler::createPerson)
.build();
Copy the code
Nested Routes
Use the PATH method to extract the same prefix for multiple requests
RouterFunction<ServerResponse> route = route()
.path("/person", builder -> builder
.GET("/{id}", accept(APPLICATION_JSON), handler::getPerson)
.POST("/person", handler::createPerson))
.build();
Copy the code
Parameter validation
You can use Spring Validation for parameter validation
-
Add the dependent
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.2.0. The Final</version> </dependency> Copy the code
-
Write an entity validator
import org.springframework.validation.Validator; public class UserValidator implements Validator { @Override public boolean supports(Class aClass) { return User.class.equals(aClass); } @Override public void validate(Object o, Errors errors) { ValidationUtils.rejectIfEmpty(errors, "name"."name.empty"); User user = (User) o; if (user.getAge() < 20) { errors.rejectValue("age"."negativevalue"); } else if (user.getAge() > 110) { errors.rejectValue("age"."too.darn.old"); }}}Copy the code
-
Application parameter verification
public Mono<ServerResponse> addUser(ServerRequest serverRequest){ // Bind the validation method in the doOnNext method serverRequest.bodyToMono(User.class) .doOnNext(this::validate); return ServerResponse.ok().body("122", String.class); } // Define the validation method private void validate(User user) { // Instantiate the entity validator Validator validator = new UserValidator(); Errors errors = new BeanPropertyBindingResult(user, "user"); validator.validate(user, errors); if (errors.hasErrors()) { throw newServerWebInputException(errors.toString()); }}Copy the code
Handlers can also through the Validator LocalValidatorFactoryBean into a global, using standard bean validation API (JSR – 303)