SpringBoot learning notes 11 web reactive web application

Based on the official spring documentation, the official address is: Spring Boot_Web

Spring Boot is very suitable for web application development. You can create a self-contained HTTP server using embedded Tomcat, Jetty, Undertow, or Netty. Most web applications use the Spring Boot starter web module to start and run quickly. You can also choose to use the Spring Boot starter weblux module to build responsive web applications.

Spring Boot simplifies the development of responsive web applications by providing automatic configuration for Spring Webflux.

1. About Spring WebFlux Framework

Spring WebFlux is a new responsive web framework introduced in Spring framework 5.0. Unlike Spring MVC, it does not require servlet API, is completely asynchronous and non blocking, and implements the Reactive Streams specification through the Reactor project.

There are two types of Spring WebFlux: functional and annotation based. The annotation based model is very close to the Spring MVC model, as shown in the following example:

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class MyRestController {

    private final UserRepository userRepository;

    private final CustomerRepository customerRepository;

    public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {
        this.userRepository = userRepository;
        this.customerRepository = customerRepository;
    }

    @GetMapping("/{user}")
    public Mono<User> getUser(@PathVariable Long userId) {
        return this.userRepository.findById(userId);
    }

    @GetMapping("/{user}/customers")
    public Flux<Customer> getUserCustomers(@PathVariable Long userId) {
        return this.userRepository.findById(userId).flatMapMany(this.customerRepository::findByUser);
    }

    @DeleteMapping("/{user}")
    public void deleteUser(@PathVariable Long userId) {
        this.userRepository.deleteById(userId);
    }

}

WebFlux is part of the Spring framework. Details can be found in its Reference documents Found in.

There is also WebFlux. First, add the spring boot starter weblux module to the application.

It should be noted that adding Spring - boot - starter web and Spring -boot-starter-webflux modules to the application will cause Spring Boot to automatically configure Spring MVC instead of WebFlux. This behavior is chosen because many Spring developers add Spring Boot starter weblux to their Spring MVC applications to use responsive webclients. However, you can still set the selected application type to Spring application Setwebapplicationtype (webapplicationtype. Reactive) to force your selection.

1.1 automatic configuration of spring Webflux

Spring Boot provides automatic configuration for Spring WebFlux, which works well in most applications.

For the automatic configuration of WebFlux, the following features are added to the default values of Spring:

  • Configure codecs for HttpMessageReader and HttpMessageWriter instances (described later in this document).

  • Support provides static resources, including support for webjar (described later in this document).

If you want to maintain the characteristics of Spring Boot WebFlux and add additional WebFlux Configuration, you can add your own @ Configuration class of WebFluxConfigurer type, but do not add @ EnableWebFlux.

If you want to fully control Spring WebFlux, you can add your own @ Configuration and @ EnableWebFlux annotations.

1.2 HTTP codec of httpmessagereaders and HttpMessageWriters

Spring WebFlux uses the HttpMessageReader and HttpMessageWriter interfaces to convert HTTP requests and responses. They are configured using CodecConfigurer and have reasonable defaults by looking at the libraries available in the classpath.

Spring Boot provides special configuration properties for codecs codec.*. It also applies further customization by using the CodecCustomizer instance. For example, spring jackson.* The configuration key is applied to the Jackson codec.

If you need to add or customize codecs, you can create a custom CodecCustomizer component. An example is as follows:

import org.springframework.boot.web.codec.CodecCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerSentEventHttpMessageReader;

@Configuration(proxyBeanMethods = false)
public class MyCodecsConfiguration {

    @Bean
    public CodecCustomizer myCodecCustomizer() {
        return (configurer) -> {
            configurer.registerDefaults(false);
            configurer.customCodecs().register(new ServerSentEventHttpMessageReader());
            // ...
        };
    }

}

By default, Spring Boot serves the static content in a directory named / static (or / public or / resources or / META-INF/resources) in the classpath. It uses the ResourceWebHandler from Spring WebFlux, so you can modify this behavior by adding your own WebFluxConfigurer and overriding the addResourceHandlers method.

By default, resources are mapped to / * * but you can set spring Weblux to optimize it. Static path pattern property. For example, relocating all resources to / resources / * * can be implemented as follows:

spring.webflux.static-path-pattern=/resources/**

You can also use spring web. resources. Static locations customize static resource locations. Doing so will replace the default with a list of directory locations. If you do, the default welcome page detection will switch to your custom location. Therefore, if there is index anywhere at startup HTML, then it is the home page of the application.

In addition to the "standard" static resource locations listed above, webjars content has special cases. Any resources whose path is in / webjars / * * will be provided from the jar file if they are packaged in webjars format.

1.3 Welcome Page

Spring Boot supports static and templated welcome pages. It first looks for index. In the configured static content location HTML file. If not, it looks for the index template. If any one is found, it is automatically used as the welcome page for the application.

1.4 template engine

Like REST web services, Spring WebFlux can also be used to provide dynamic HTML content. Spring WebFlux supports a variety of template technologies, including Thymeleaf, FreeMarker and Mustache.
Spring Boot includes automatic configuration support for the following template engines:

  • FreeMarker
  • Thymeleaf
  • Mustache

When using the default configuration of the above template engine, your template will be automatically selected from src/main/resources/templates.

1.5 error handling

Spring Boot provides a WebExceptionHandler that handles all errors in a reasonable way. Its position in the processing order precedes the handler provided by WebFlux, which is considered to be the last. For the machine client, it generates a JSON response with details of the error, HTTP status, and exception messages. For the browser client, there is a "white tag" error handler that renders the same data in HTML format. You can also provide your own HTML template to display errors.

The first step in customizing this feature usually involves using existing mechanisms, but replacing or adding error content. To do this, you can add a bean of type ErrorAttributes.

To change the error handling behavior, you can implement ErrorWebExceptionHandler and register the bean definition of this type. Because ErrorWebExceptionHandler is quite low-level, Spring Boot also provides a convenient AbstractErrorWebExceptionHandler to handle errors in the way of WebFlux function, as shown in the following example:

import reactor.core.publisher.Mono;

import org.springframework.boot.autoconfigure.web.WebProperties.Resources;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.function.server.ServerResponse.BodyBuilder;

@Component
public class MyErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

    public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, Resources resources,
            ApplicationContext applicationContext) {
        super(errorAttributes, resources, applicationContext);
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(this::acceptsXml, this::handleErrorAsXml);
    }

    private boolean acceptsXml(ServerRequest request) {
        return request.headers().accept().contains(MediaType.APPLICATION_XML);
    }

    public Mono<ServerResponse> handleErrorAsXml(ServerRequest request) {
        BodyBuilder builder = ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR);
        // ... additional builder calls
        return builder.build();
    }

}

For a more comprehensive picture, you can subclass DefaultErrorWebExceptionHandler directly and override specific methods.

In some cases, errors handled at the controller or handler function level are not logged by the measurement infrastructure. By setting the exceptions handled as request properties, the application can ensure that these exceptions are recorded in the request metrics:

import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.reactive.result.view.Rendering;
import org.springframework.web.server.ServerWebExchange;

@Controller
public class MyExceptionHandlingController {

    @GetMapping("/profile")
    public Rendering userProfile() {
        // ...
        throw new IllegalStateException();
    }

    @ExceptionHandler(IllegalStateException.class)
    public Rendering handleIllegalState(ServerWebExchange exchange, IllegalStateException exc) {
        exchange.getAttributes().putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, exc);
        return Rendering.view("errorView").modelAttribute("message", exc.getMessage()).build();
    }

}

1.6 custom error page

If you want to display a custom HTML error page for a given status code, you can add a file to the / error directory. The error page can be static HTML (that is, added to any static resource directory) or built with a template. The name of the file should be the exact status code or series mask.

For example, if 404 is mapped to a static HTML file, the directory structure can be as follows:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

Use the Mustache template to map all 5xx errors. The directory structure can be as follows:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.mustache
             +- <other templates>

1.7 Web filter

Spring WebFlux provides a WebFilter interface, which can be implemented to filter HTTP request response exchange. The WebFilter bean found in the application context is automatically used to filter each exchange.

Where the Order of filters is important, they can implement Ordered or annotate with @ Order. Spring Boot auto configuration allows you to configure web filters for it. For example, the Order in the following filter example:

Web FilterOrder
MetricsWebFilterOrdered.HIGHEST_PRECEDENCE + 1
WebFilterChainProxy (Spring Security)-100
HttpTraceWebFilterOrdered.LOWEST_PRECEDENCE - 10

2. Embedded responsive server support

Spring Boot supports the following embedded responsive web servers: Reactor Netty, Tomcat, Jetty, and Undertow. Most developers use the appropriate "Starter" to get a fully configured instance. By default, the embedded server listens for HTTP requests on port 8080.

3. Responsive server resource configuration

When the Reactor Netty or Jetty server is automatically configured, Spring Boot will create specific bean s that will provide HTTP resources for the server instance: ReactorResourceFactory or JettyResourceFactory.

By default, these resources will also be shared with Reactor Netty and Jetty clients for optimal performance:

  • The same technology is also used for servers and clients
  • The client instance is built using WebClient. Spring Boot automatically configures the Builder bean

Developers can override the resource configuration of Jetty and Reactor Netty by providing a custom ReactorResourceFactory or JettyResourceFactory bean -- this will be applied to clients and servers.

You can learn more about in the WebClient Runtime section Client resource configuration Information about.

Keywords: Java Spring Spring Boot

Added by grungefreak on Tue, 04 Jan 2022 07:47:23 +0200