3年前 (2021-08-21)  相关技术 |   抢沙发  1520 
文章评分 0 次,平均分 0.0

Spring WebFlux教程:如何构建反应式web应用程序

反应式系统允许我们在高数据流世界中所需的无与伦比的响应能力和可扩展性。然而,反应式系统需要经过专门培训的工具和开发人员来实现这些独特的程序体系结构。Spring WebFlux with Project Reactor是专门为满足现代公司的反应性需求而构建的框架。

今天,我们将通过解释WebFlux如何与其他反应式堆栈工具相匹配、如何不同以及如何制作第一个应用程序来帮助您开始使用WebFlux。

什么是反应式系统?

反应式系统是采用反应式体系结构模式设计的系统,该模式优先使用松散耦合、灵活和可扩展的组件。它们还设计了故障解决方案,以确保即使有一个系统出现故障,大多数系统仍能运行。

反应式系统专注于:

  • 反应性:最重要的是,反应性系统应该快速响应任何用户输入。反应式系统的拥护者认为,反应性有助于优化系统的所有其他部分,从数据收集到用户体验。
  • 弹性:反应式系统的设计应能预测系统故障。反应式系统期望组件最终会发生故障,并设计松散耦合的系统,即使几个单独的部件停止工作,也能保持活动状态。
  • 弹性:反应式系统应通过放大或缩小以满足需求来适应工作负载的大小。许多反应式系统还将使用预测缩放来预测和准备突然的变化。实现弹性的关键是消除任何瓶颈,构建能够根据需要分割或复制组件的系统。
  • 消息驱动通信:反应式系统的所有组件都是松散耦合的,每个组件之间都有硬边界。您的系统应该通过显式消息传递跨越这些边界进行通信。这些消息使不同的组件了解故障,并帮助他们将工作流委派给能够处理它的组件。

反应式和其他web模式之间最显著的区别是,反应式系统可以一次执行多个未阻塞的调用,而不是让一些调用等待其他调用。因此,反应式系统可以加快性能和响应速度,因为web应用程序的每个部分都可以比等待另一部分更快地完成自己的部分。

简而言之,反应式系统使用松散耦合、无阻塞的组件来提高性能、用户体验和错误处理。

什么是Project Reactor

Project Reactor是由Pivotal构建的框架,由Spring提供动力。它实现了反应式API模式,最显著的是反应式流规范。

如果您熟悉Java8流,您会很快发现流和流量(或其单元素版本Mono)之间有许多相似之处。它们之间的主要区别在于Flux和Monos遵循发布者-订阅者模式并实现背压,而StreamAPI则没有。

背压是数据端点向数据生产者发出信号,表示其接收的数据过多的一种方式。这允许更好的流管理和分发,因为它可以防止单个组件过度工作。

使用Reactor的主要优点是您可以完全控制数据流。您可以依赖订阅者在准备处理信息时请求更多信息的能力,或者在发布者端缓冲一些结果,甚至使用无背压的完全推送方法。

在我们的反应式堆栈中,它位于Spring Boot 2.0之下和WebFlux之上:

Spring WebFlux教程:如何构建反应式web应用程序

什么是Spring WebFlux

Spring WebFlux是一个完全非阻塞的、基于注释的web框架,它构建在ProjectReactor上,使得在HTTP层上构建反应式应用程序成为可能。WebFlux使用一个新的路由器功能特性将功能编程应用到web层,并绕过声明性控制器和请求映射。WebFlux要求您将Reactor作为核心依赖项导入。

WebFlux是在Spring 5中添加的,作为Spring MVC的一种被动替代方案,并增加了对以下方面的支持:

  • 非阻塞线程:在不等待前一个任务完成的情况下完成其指定任务的并发线程。
  • Reactive Stream API:一个标准化的工具,包括异步流处理选项和非阻塞背压。
  • 异步数据处理:当数据在后台处理时,用户可以继续使用正常的应用程序功能而不会中断。

最终,WebFlux取消了SpringMVCs每请求线程模型,而是使用multi-EventLoop非阻塞模型来支持反应式、可伸缩的应用程序。由于支持Netty、Undertow和Servlet3.1+容器等流行服务器,WebFlux已成为反应式堆栈的关键部分。

Spring WebFlux的显著特征

路由器功能

RouterFunction是标准SpringMVC中使用的@RequestMapping@Controller注释样式的功能替代品。

我们可以使用它将请求路由到处理程序函数:

@RestController
public class ProductController {
    @RequestMapping("/product")
    public List<Product> productListing() {
        return ps.findAll();
    }
}

您可以使用RouterFunctions.route()创建路由,而不是编写完整的路由器函数。路由注册为Springbean,因此可以在任何配置类中创建。

路由器功能避免了由请求映射的多步骤过程引起的潜在副作用,而是将其简化为直接的路由器/处理程序链。这允许反应式编程的功能性编程实现。

RequestMappingController注释样式在WebFlux中仍然有效,如果您对旧样式更熟悉,RouterFunction只是解决方案的一个新选项。

WebClient

WebClient是WebFlux的反应式web客户端,由著名的RestTemplate构建。它是一个接口,表示web请求的主要入口点,并支持同步和异步操作。WebClient主要用于反应式后端到后端通信。

您可以通过使用Maven导入标准WebFlux依赖项来构建和创建WebClient实例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
WebClient client = WebClient.create();

Reactive Steam API

Reactive Steam API是一个导入的函数集合,允许更智能的流数据流。它内置了对背压和异步处理的支持,确保应用程序最有效地利用计算机和组件资源。

反应流API中有四个主要接口:

1. Publisher:根据链接订阅者的需求向其发送事件。充当订阅者可以监视事件的中心链接点。

2. Subscriber:接收和处理发布服务器发出的事件。多个订阅服务器可以链接到单个发布服务器,并对同一事件做出不同的响应。可以将订阅服务器设置为响应:

  • onNext,当它接收到下一个事件时。
  • onSubscribe,当添加新订户时
  • onError,当另一个订阅服务器发生错误时
  • onComplete,当另一个订阅服务器完成其任务时

3. Subscription:定义所选发布服务器和订阅服务器之间的关系。每个订阅服务器只能链接到一个发布服务器。

4. Processor:表示订阅服务器的处理阶段

Servers

WebFlux在Tomcat、Jetty、Servlet3.1+容器以及Netty和Undertow等非Servlet运行时上受支持。Netty最常用于异步和非阻塞设计,因此WebFlux将默认使用它。只需对Maven或Gradle构建软件进行简单更改,就可以轻松地在这些服务器选项之间切换。

这使得WebFlux在可使用的技术方面具有高度的通用性,并允许您轻松地在现有基础架构中实现它。

并发模型

WebFlux的构建考虑了非阻塞性,因此使用了与SpringMVC不同的并发编程模型。

SpringMVC假设线程将被阻塞,并使用一个大的线程池在阻塞实例期间保持移动。这个更大的线程池使得MVC资源更加密集,因为计算机硬件必须同时保持更多线程的运行。

WebFlux使用了一个小线程池,因为它假设您永远不需要通过工作来避免阻塞。这些线程称为事件循环工作线程,在数量上是固定的,在传入请求中的循环速度比MVC线程快。这意味着WebFlux可以更有效地使用计算机资源,因为活动线程总是在工作。

Spring WebFlux安全

WebFlux使用Spring Security实现身份验证和授权协议。Spring Security使用WebFilter根据经过身份验证的用户列表检查请求,也可以将其设置为自动拒绝符合来源或请求类型等条件的请求。

@EnableWebFluxSecurity
public class HelloWebFluxSecurityConfig {
    @Bean
    public MapReactiveUserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("user")
            .roles("USER")
            .build();
        return new MapReactiveUserDetailsService(user);
    }
}

这是一个将所有设置设置为默认值的最小实现。在这里,我们可以看到用户有一个用户名、一个密码和一个或多个角色标签,允许他们进行一定程度的访问。

开始使用SpringWebFlux

现在,让我们亲身体验WebFlux。首先,我们需要建立一个项目。我们将使用SpringInitializer生成一个带有SpringReactiveWeb依赖项的Maven构建。

Spring WebFlux教程:如何构建反应式web应用程序

这将生成一个像下面的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>reactive-rest-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>reactive-rest-service</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

现在你已经拥有了继续下去所需的一切!从这里我们将添加一些组件来制作Hello World应用程序。我们将只添加一个路由器和一个处理程序,这是创建基本WebFlux应用程序的最低要求。

Router

首先,我们将创建一个示例路由器,在URL上显示一次文本http://localhost:8080/example. 这定义了用户如何请求我们将在处理程序中定义的数据。

@Configuration
public class ExampleRouter {
  @Bean
  public RouterFunction<ServerResponse> routeExample (ExampleHandler exampleHandler) {
    return RouterFunctions
        .route(RequestPredicates.GET("/example").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), exampleHandler::hello);
  }
}

Handler

现在,我们将添加一个处理程序,用于侦听请求/示例路由的任何用户。一旦路由器识别出请求的路径匹配,它就会将用户发送到处理程序。我们的处理程序接收消息并将用户带到带有我们问候语的页面。

@Component
public class ExampleHandler {
  public Mono<ServerResponse> hello(ServerRequest request) {
    return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
         .body(BodyInserters.fromObject("Hello, Spring WebFlux Example!"));
  }
}

运行应用程序

现在,我们将通过执行Maven命令spring boot:run来运行应用程序。您现在可以访问http://localhost:8080/example 在浏览器中查找:

Hello, Spring WebFlux Example!

原文地址:https://www.educative.io/blog/spring-webflux-tutorial

 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/2251.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册