ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 构建反应式RESTful Web服务 本指南将引导您完成创建“ Hello,Spring!”的过程。 带有Spring WebFlux(版本5的新功能)的RESTful Web服务,然后通过WebClient(版本5的新功能)使用该服务。 本指南展示了使用Spring WebFlux的功能方法。 您还可以 将注释与WebFlux一起使用 。 ## 你会建立什么 您将使用Spring Webflux和该服务的WebClient使用者构建RESTful Web服务。 您将能够在System.out和以下位置看到输出: ~~~ http://localhost:8080/hello ~~~ ## 您将需要什么 * 约15分钟 * 最喜欢的文本编辑器或IDE * [JDK 1.8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 或更高版本 * [Gradle 4+](http://www.gradle.org/downloads) 或 [Maven 3.2+](https://maven.apache.org/download.cgi) * 您还可以将代码直接导入到IDE中: * [弹簧工具套件(STS)](https://spring.io/guides/gs/sts) * [IntelliJ IDEA](https://spring.io/guides/gs/intellij-idea/) ## 如何完成本指南 像大多数Spring 一样 [入门指南](https://spring.io/guides) ,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。 无论哪种方式,您最终都可以使用代码。 要 **从头开始** ,请继续进行“ [从Spring Initializr开始”](https://spring.io/guides/gs/reactive-rest-service/#scratch) 。 要 **跳过基础知识** ,请执行以下操作: * [下载](https://github.com/spring-guides/gs-reactive-rest-service/archive/master.zip) 并解压缩本指南的源存储库,或使用 对其进行克隆 [Git](https://spring.io/understanding/Git) : `git clone [https://github.com/spring-guides/gs-reactive-rest-service.git](https://github.com/spring-guides/gs-reactive-rest-service.git)` * 光盘进入 `gs-reactive-rest-service/initial` * 继续 [创建WebFlux处理程序](https://spring.io/guides/gs/reactive-rest-service/#initial) 。 **完成后** ,您可以根据中的代码检查结果 `gs-reactive-rest-service/complete`. ## 从Spring Initializr开始 如果您使用Maven,请访问 [Spring Initializr](https://start.spring.io/#!type=maven-project&language=java&platformVersion=2.4.3.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=reactive-rest-service&name=reactive-rest-service&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.reactive-rest-service&dependencies=webflux) 以生成具有所需依赖项的新项目(Spring Web Reactive)。 以下清单显示了 `pom.xml` 选择Maven时创建的文件: ~~~ <?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.3</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> ~~~ 如果您使用Gradle,请访问 [Spring Initializr](https://start.spring.io/#!type=gradle-project&language=java&platformVersion=2.4.3.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=reactive-rest-service&name=reactive-rest-service&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.reactive-rest-service&dependencies=webflux) 以生成具有所需依赖项的新项目(Spring Web Reactive)。 以下清单显示了 `build.gradle` 选择Gradle时创建的文件: ~~~ plugins { id 'org.springframework.boot' version '2.4.3' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-webflux' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.projectreactor:reactor-test' } test { useJUnitPlatform() } ~~~ ### 手动初始化(可选) 如果要手动初始化项目而不是使用前面显示的链接,请按照以下步骤操作: 1. 导航到 [https://start.spring.io](https://start.spring.io) 。 该服务提取应用程序所需的所有依赖关系,并为您完成大部分设置。 2. 选择Gradle或Maven以及您要使用的语言。 本指南假定您选择了Java。 3. 单击 **Dependencies,** 然后选择 **Spring Reactive Web** 。 4. 点击 **生成** 。 5. 下载生成的ZIP文件,该文件是使用您的选择配置的Web应用程序的存档。 如果您的IDE集成了Spring Initializr,则可以从IDE中完成此过程。 ## 创建一个WebFlux处理程序 在Spring Reactive方法中,我们使用处理程序来处理请求并创建响应,如以下示例所示: `src/main/java/hello/GreetingHandler.java` ~~~ package hello; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; @Component public class GreetingHandler { public Mono<ServerResponse> hello(ServerRequest request) { return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN) .body(BodyInserters.fromValue("Hello, Spring!")); } } ~~~ 这个简单的反应式类始终返回“ Hello,Spring!”。 它可能返回许多其他内容,包括来自数据库的项目流,通过计算生成的项目流,等等。 请注意反应性代码: `Mono` 持有一个的对象 `ServerResponse` 身体。 ## 创建一个路由器 在此应用程序中,我们使用路由器来处理我们公开的唯一路由( `/hello`),如以下示例所示: `src/main/java/hello/GreetingRouter.java` ~~~ package hello; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.server.RequestPredicates; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; @Configuration public class GreetingRouter { @Bean public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) { return RouterFunctions .route(RequestPredicates.GET("/hello").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), greetingHandler::hello); } } ~~~ 路由器侦听路由器上的流量 `/hello` 路径并返回我们的反应性处理程序类提供的值。 ## 创建一个WebClient Spring MVC RestTemplate类本质上是阻塞的。 因此,我们不想在反应性应用程序中使用它。 对于反应性应用,Spring提供了 `WebClient`类,这是非阻塞的。 我们使用WebClient实现来使用我们的RESTful服务: `src/main/java/hello/GreetingWebClient.java` ~~~ package hello; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; public class GreetingWebClient { private WebClient client = WebClient.create("http://localhost:8080"); private Mono<ClientResponse> result = client.get() .uri("/hello") .accept(MediaType.TEXT_PLAIN) .exchange(); public String getResult() { return ">> result = " + result.flatMap(res -> res.bodyToMono(String.class)).block(); } } ~~~ 这 `WebClient` 类使用反应性功能,形式为 `Mono` 来保存我们指定的URI的内容和一个函数(在 `getResult`方法)将内容转换为字符串。 如果我们有不同的要求,则可以将其转换为字符串以外的形式。 因为我们要把结果放入 `System.out`,字符串在这里起作用。 您可以使用 WebClient 与非反应式阻塞服务进行通信。 ## 使应用程序可执行 尽管您可以将此服务打包为传统的 [WAR](https://spring.io/understanding/WAR) 文件,以部署到外部应用程序服务器,但是下面演示的更简单的方法创建了一个独立的应用程序。 您将所有内容打包在一个可执行的JAR文件中,由一个好的旧Java驱动 `main()`方法。 在此过程中,您使用Reactive Spring的支持将Netty服务器作为HTTP运行时嵌入,而不是部署到外部实例。 `src/main/java/hello/Application.java` ~~~ package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); GreetingWebClient gwc = new GreetingWebClient(); System.out.println(gwc.getResult()); } } ~~~ `@SpringBootApplication` 是一个方便注释,它添加了以下所有内容: * `@Configuration`:将类标记为应用程序上下文的Bean定义的源。 * `@EnableAutoConfiguration`:告诉Spring Boot根据类路径设置,其他bean和各种属性设置开始添加bean。 例如,如果 `spring-webmvc` 在类路径上,此注释将应用程序标记为Web应用程序并激活关键行为,例如设置 `DispatcherServlet`. * `@ComponentScan`:告诉Spring在服务器中寻找其他组件,配置和服务 `hello` 包,让它找到控制器。 这 `main()` 方法使用Spring Boot的 `SpringApplication.run()`启动应用程序的方法。 您是否注意到没有一行XML? 没有 `web.xml`文件。 该Web应用程序是100%纯Java,因此您无需处理任何管道或基础结构。 ### 建立可执行的JAR 您可以使用Gradle或Maven从命令行运行该应用程序。 您还可以构建一个包含所有必需的依赖项,类和资源的可执行JAR文件,然后运行该文件。 生成可执行jar使得在整个开发生命周期中,跨不同环境等等的情况下,都可以轻松地将服务作为应用程序进行发布,版本控制和部署。 如果您使用Gradle,则可以通过使用以下命令运行该应用程序 `./gradlew bootRun`。 或者,您可以通过使用以下命令构建JAR文件: `./gradlew build` 然后运行JAR文件,如下所示: ~~~ java -jar build/libs/gs-reactive-rest-service-0.1.0.jar ~~~ 如果您使用Maven,则可以通过使用以下命令运行该应用程序 `./mvnw spring-boot:run`。 或者,您可以使用以下命令构建JAR文件: `./mvnw clean package` 然后运行JAR文件,如下所示: ~~~ java -jar target/gs-reactive-rest-service-0.1.0.jar ~~~ 此处描述的步骤将创建可运行的JAR。 您还可以 构建经典的WAR文件 。 显示日志记录输出。 该服务应在几秒钟内启动并运行。 服务启动后,您会看到以下内容: `>> result = Hello, Spring!` 该行来自WebClient正在使用的反应式内容。 自然,与将输出放入System.out相比,您会发现与输出更有趣的事情。 ## 测试应用 现在该应用程序正在运行,您可以对其进行测试。 首先,您可以打开浏览器并转到 `[http://localhost:8080/hello](http://localhost:8080/hello)`然后看,“你好,春天!” 在本指南中,我们还创建了一个测试类,以帮助您开始使用 `WebTestClient` 班级。 `src/test/java/hello/GreetingRouterTest.java` ~~~ package hello; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; @ExtendWith(SpringExtension.class) // We create a `@SpringBootTest`, starting an actual server on a `RANDOM_PORT` @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class GreetingRouterTest { // Spring Boot will create a `WebTestClient` for you, // already configure and ready to issue requests against "localhost:RANDOM_PORT" @Autowired private WebTestClient webTestClient; @Test public void testHello() { webTestClient // Create a GET request to test an endpoint .get().uri("/hello") .accept(MediaType.TEXT_PLAIN) .exchange() // and use the dedicated DSL to test assertions against the response .expectStatus().isOk() .expectBody(String.class).isEqualTo("Hello, Spring!"); } } ~~~ ## 概括 恭喜你! 您已经开发了一个Reactive Spring应用程序,其中包括一个使用RESTful服务的WebClient!