Spring 5 WebFlux的反应式编程

介绍

Spring WebFlux是Spring对日益增长的阻塞I / O体系结构问题的回应。

随着数据在我们这个时代变得越来越重要,我们采取的检索和处理数据的方法也在发生变化。 按照惯例,大多数方法都是“阻塞”的,或者说是同步的 。 这意味着访问资源会阻止应用程序访问/处理另一资源,直到处理了先前的资源为止。

尽管通过高性能应用程序对数据的需求不断增长,但是在有限的数据和资源量的情况下,这是完全可以的,这成为一个巨大的问题。

解决方案很明显-让更多的文员处理客户。 在软件应用程序方面,这意味着多线程环境和异步,非阻塞调用。

spring反应式编程

由Spring MVC组成的Spring流行的servlet堆栈使用访问和处理数据的常规方法作为同步调用。 随着Spring 5的推出,Spring的反应式是在Reactor Core之上构建的。

Spring的反应式堆栈为Netty和Servlet 3.1+容器提供了额外的支持,从而提高了反应式应用程序的性能:


spring WebFlux

Spring WebFlux是Spring MVC的对应模块。 在Spring MVC实现同步,阻塞I / O的地方,Spring WebFlux通过Reactive Streams实现反应编程。

尽管可以自由地将它们组合在一起,但是通常将使用其中一个。

Spring WebFlux依赖关系

通过Spring Initializr初始化一个普通的Spring Boot项目,添加一个依赖项就足够了:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-webflux</artifactId> 
    <version>{version}</version> 
</dependency> 

spring-boot-starter-webflux包括spring-web , spring-webflux , spring-boot-starter , spring-boot-starter-reactor-netty等,因此不需要任何其他依赖项。

对于使用Gradle进行依赖关系管理的应用程序,可以将Spring WebFlux添加到应用程序的build.gradle文件中:

 compile group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: '2.2.2.RELEASE' 

 

在Spring WebFlux中,从任何操作返回的数据都打包到响应流中。 这种方法体现了两种类型,它们是WebFlux应用程序的构建块-Mono和Flux 。

Mono是返回零个项目或单个项目( 0..1 )的流,而Flux是返回零个或多个项目( 0..N )的流。

因此,在期望单个(或没有)结果(例如从数据库中检索唯一用户)时,将使用Mono ,而在期望多个结果或某种类型的集合时,将使用Flux 。

Spring WebFlux控制器

与我们在经典Spring MVC中使用控制器的方式类似,为了创建异步REST API,我们使用WebFlux控制器。 甚至命名约定也类似,以确保在这两种方法之间轻松转换。

为了将一个类标记为控制器,我们在类级别使用@RestController批注。

在类路径中具有Spring WebFlux和Reactor Core依赖项将使Spring知道@RestController实际上是一个反应组件,并添加对MonoFlux支持。

 

Spring WebFlux配置

按照Spring Boot的标准,我们将通过注释处理配置。 @Configuration@EnableWebFlux批注将一个类标记为配置类,Spring的bean管理人员将其注册:

 @Configuration @EnableWebFlux 
public class WebFluxConfig {
} 

要使用或扩展现有的WebFlux配置API,可以扩展WebFluxConfigurer接口:

 @Configuration @EnableWebFlux 
public class WebFluxConfig implements WebFluxConfigurer {
} 

带有Spring WebFlux的CORS

WebFlux还提供CORS(跨源资源共享)支持,与Spring MVC Servlet堆栈非常相似。 可以在项目级别以及控制器和控制器方法级别设置CORS配置。

要在项目级别添加CORS配置,您需要从WebFluxConfigurer界面addCorsMappings()方法:

 @Configuration 
@EnableWebFlux 
public class WebFluxConfig implements WebFluxConfigurer { 
@Override 
public void addCorsMappings(CorsRegistry registry) { 
   registry.addMapping("/api/**") 
          .allowedOrigins("http://www.stackabuse.com") 
          .allowedMethods("GET", "PUT", "DELETE") 
          .allowedHeaders("testHeader") 
          .allowCredentials(true); 
   } 
} 

为了更详细地添加CORS配置,使用了@CrossOrigin批注。 这允许在控制器和方法级别指定CORS详细信息。

在控制器类级别使用@CrossOrigin时,所有方法级别的CORS设置都将从类级别配置继承:

 @CrossOrigin(origins = "https://www.stackabuse.com") 
@RestController @RequestMapping("/resource") 
public class ResourceController { 
@GetMapping("/{id}") 
public Mono<Resource> getResource(@PathVariable String id) { 
   } 
} 

Spring Webflux的安全性

Spring还为其WebFlux框架提供了标准的安全性选项。 您需要在类级别添加@EnableWebFluxSecurity ,以在项目中启用安全性配置:

 @EnableWebFluxSecurity 
public class WebfluxSecurity { 
@Bean 
public SecurityWebFilterChain springSecurityFilterChain( ServerHttpSecurity http) {     
    http.csrf().disable() .authorizeExchange() .pathMatchers(HttpMethod.GET, 
    "/resource/").hasRole("ADMIN") .pathMatchers("/**").permitAll() .and() 
    .httpBasic(); 
    return http.build(); 
} 
} 

Spring WebFlux Web客户端

Spring WebFlux还包括一个反应式Web客户端,用于管理REST调用。 默认情况下,使用Reactor-Netty与WebFlux服务器进行通信。

可以使用静态工厂方法或通过其构建器方法(更多的自定义)来创建WebFlux客户端对象。

静态工厂方法是WebClient.create()WebClient.create(String baseUrl) 。 另一方面, WebClient.builder提供以下选项以向Web客户端对象添加更多详细信息:

  • uriBuilderFactory
  • defaultHeader
  • defaultCookie
  • defaultRequest
  • filter
  • exchangeStrategies
  • clientConnector

我们将在构建演示应用程序的进行部分中对此进行仔细研究。

演示申请

我们将使用WebFlux的标准组件创建一个简单的反应式REST API,它将用作反应式服务器。 然后,将构建一个反应式Web客户端应用程序,该应用程序从该服务器检索信息并处理数据。

WebFlux Web服务器

资料库

首先,通过创建反应式存储库接口为反应式应用程序奠定基础。

 public interface ResourceRepository extends ReactiveCrudRepository<Resource, String> {
} 

 

我们从WebFlux的ReactiveCrudRepository扩展了存储库,该存储库将根据MonoFlux数据类型返回数据,具体取决于可以检索的元素数。

要将MongoDB与Spring WebFlux结合使用,我们将添加一个配置类,该类告诉Spring应该将数据库作为反应性组件进行处理:

 @EnableReactiveMongoRepositories 
public class MongoDbConfiguration extends AbstractReactiveMongoConfiguration { 
  @Override 
  public MongoClient reactiveMongoClient() { 
     return MongoClients.create(); 
  } 
  @Override 
  protected String getDatabaseName() { 
    return "testDatabase";
 } 
} 

控制者

完成并配置数据层后,让我们创建一个简单的REST控制器,该控制器将通过GET请求检索MonoFlux资源:

  @RestController 
 @RequestMapping("/resource")
 public class ResourceController { 
 @Autowired 
 ResourceRepository resourceRepository;
 @GetMapping("/{id}")
 public Mono<Resource> getResource(@PathVariable String id) { 
     return resourceRepository.findById(id); 
 } 
 @GetMapping 
 public Flux<Resource> getResources() {
    return resourceRepository.findAll(); 
 } 
} 

在这里,我们使用反应式ResourceRepository来查找来自请求的id的资源。 由于我们正在寻找唯一的ID,因此预期结果是1条记录(找到带有传递ID的资源)或0条记录(数据库中没有记录),因此将Mono用作返回类型。

由于findAll()可以返回一个以上的资源元素(如果存在),因此将Flux用作返回类型。

WebFlux Web客户端

现在我们已经建立了一个基本的REST应用程序,让我们创建一个Spring WebFlux客户端,该客户端可以将请求发送到WebFlux REST应用程序。

要启动Web客户端,我们需要使用服务器URL创建一个WebClient对象:

 public WebClient openConnection(String url) {
 client = WebClient.create(url); 
 return client;
} 

创建WebClient对象后,我们可以使用它向Web服务器发出请求。

让我们向服务器发出请求,以给定ID检索资源:

 public void getResourceById(String id) { 
   Mono<Resource> result = client.get() 
   .uri("/resource/{id}", "1") .retrieve() 
   .bodyToMono(Resource.class); 
   result.subscribe(System.out::println);
} 

bodyToMono()方法负责将响应的正文包装到Mono 。

同样,如果调用端点将数据返回为Flux则可以使用以下方法检索它:

 public void getAllResources() 
{ 
 Flux<Resource> result = client.get() 
 .uri("/resource") 
 .retrieve() 
 .bodyToFlux(Resource.class); 
  result.subscribe(System.out::println);
} 

结论

Spring框架允许开发人员使用Spring的WebFlux堆栈制作反应性,非阻塞的应用程序和API。 WebFlux提供的注释与经典Spring MVC应用程序中使用的注释非常相似,这使开发人员可以更轻松地过渡到反应式代码。

在本指南中,我们介绍了WebFlux框架的最重要概念,并构建了一个演示应用程序以在实践中展示它们。

posted @ 2020-06-10 09:07  时间都哪去了  阅读(769)  评论(0编辑  收藏  举报