Spring WebFlux(一)


Reactive

反應系統具有某些特性,使其非常適合低延遲,高吞吐量的工作負載。Project Reactor 和 Spring 產品組合一起使開發人員能夠構建可響應,有彈性,有彈性和消息驅動的企業級反應系統。

什么是 reactive processing?

響應式處理是使開發人員能夠構建可處理背壓(流控制)的非阻塞異步應用程序的范例。

為什么使用 reactive processing?

反應系統更好地利用了現代處理器。同樣,在反應式編程中包含背壓可確保解耦組件之間的彈性更好。

Project Reactor

Project Reactor 是一個完全無阻塞的基礎,其中包括背壓支持。它是Spring生態系統中反應式堆的基礎,並且在諸如Spring WebFlux,Spring Data和Spring Cloud Gateway等項目中得到了突出體現。

Reactive Microservices

開發人員從阻塞代碼轉移到非阻塞代碼的主要原因之一是效率。反應性代碼用更少的資源就能完成更多工作。 Project Reactor 和 Spring WebFlux 使開發人員可以利用下一代多核處理器來處理潛在的大量並發連接。通過反應式處理,您可以使用更少的微服務實例來滿足更多並發用戶的需求。

Reactive Microservices With Spring Boot

Spring產品組合提供了兩個並行技術棧。一種基於帶有Spring MVC和Spring Data結構的Servlet API。另一個是完全響應式堆棧,該技術棧利用了 Spring WebFlux 和 Spring Data 的響應式存儲庫。在這兩種情況下,Spring Security 都為兩個技術棧都提供了支持。

img

Integration with common technologies

以反應方式訪問和處理數據很重要。 MongoDB,Redis和Cassandra在Spring Data中都具有原生響應式支持。許多關系數據庫(Postgres,Microsoft SQL Server,MySQL,H2和Google Spanner)都通過R2DBC提供了響應式支持。在消息傳遞領域,Spring Cloud Stream還支持對 RabbitMQ 和 Kafka 等平台的反應式訪問。

構建一個反應式 RESTful web 服務

構建環境

  • Java 1.8 以上
  • Maven 3.2 或 Gradle 4 以上

操作流程

創建一個 Maven 項目,添加 Maven 依賴

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>2.4.1</version>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <version>2.4.1</version>
  </dependency>
  <dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <version>3.4.1</version>
    <scope>test</scope>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

創建一個 WebFlux Handler(類似之前Service)

package com.holddie.flux.hello;

import reactor.core.publisher.Mono;

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;

@Component
public class GreetingHandler {
  public Mono<ServerResponse> hello(ServerRequest request) {
    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
      .body(BodyInserters.fromValue("hello " + request.queryParam("name").get()));
  }
}

創建一個 Router(類似 Controller 路由注冊)

@Configuration
public class GreetingRouter {
	@Bean
	public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) {
		return RouterFunctions.route(RequestPredicates.GET("/hello")
				.and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), greetingHandler::hello);
	}
}

創建一個 WebClient

public class GreetingWebClient {

  private WebClient client = WebClient.create("http://localhost:8080");

  private Mono<ClientResponse> result = client.get()
    .uri("/hello?name=thomas")
    .accept(MediaType.APPLICATION_JSON)
    .exchange();

  public String getResult() {
    return ">> result = " + result.flatMap(res -> res.bodyToMono(String.class)).block();
  }
}

創建一個 SpringBoot 啟動類

@SpringBootApplication
public class HelloFluxApplication {
  public static void main(String[] args) {
    SpringApplication.run(HelloFluxApplication.class);
    GreetingWebClient greetingWebClient = new GreetingWebClient();
    System.out.println(greetingWebClient.getResult());
  }
}

編寫測試類

測試訪問 http://localhost:8080/hello?name=thomas 返回 hello thomas

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)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloFluxApplicationTest {

  @Autowired
  private WebTestClient webTestClient;

  @Test
  public void testHello() {
    webTestClient.get().uri("hello?name=thomas")
      .accept(MediaType.APPLICATION_JSON)
      .exchange().expectStatus().isOk()
      .expectBody(String.class).isEqualTo("hello thomas");
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM