SpringBoot中的响应式web应用

简介: SpringBoot中的响应式web应用

目录



简介



在Spring 5中,Spring MVC引入了webFlux的概念,webFlux的底层是基于reactor-netty来的,而reactor-netty又使用了Reactor库。


本文将会介绍在Spring Boot中reactive在WebFlux中的使用。


Reactive in Spring


前面我们讲到了,webFlux的基础是Reactor。 于是Spring Boot其实拥有了两套不同的web框架,第一套框架是基于传统的Servlet API和Spring MVC,第二套是基于最新的reactive框架,包括 Spring WebFlux 和Spring Data的reactive repositories。



image.png


我们用上面的一张图可以清晰的看到两套体系的不同。


对于底层的数据源来说,MongoDB, Redis, 和 Cassandra 可以直接以reactive的方式支持Spring Data。而其他很多关系型数据库比如Postgres, Microsoft SQL Server, MySQL, H2 和 Google Spanner 则可以通过使用R2DBC 来实现对reactive的支持。


而Spring Cloud Stream甚至可以支持RabbitMQ和Kafka的reactive模型。


下面我们将会介绍一个具体的Spring Boot中使用Spring WebFlux的例子,希望大家能够喜欢。


注解方式使用WebFlux



要使用Spring WebFlux,我们需要添加如下的依赖:


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


只用注解的方式和普通的Spring MVC的方式很类似,我们可以使用@RestController表示是一个rest服务,可以使用 @GetMapping("/hello") 来表示一个get请求。


不同之处在于,我们请求的产生方式和返回值。


熟悉Reactor的朋友可能都知道,在Reactor中有两种产生序列的方式,一种是Flux一种是Mono,其中Flux表示1或者多,而Mono表示0或者1。


看一下我们的Controller该怎么写:


@RestController
public class WelcomeController {
    @GetMapping("/hello")
    public Mono<String> hello() {
        return Mono.just("www.flydean.com");
    }
    @GetMapping("/hellos")
    public Flux<String> getAll() {
        //使用lambda表达式
        return Flux.fromStream(Stream.of("www.flydean.com","flydean").map(String::toLowerCase));
    }
}


这个例子中,我们提供了两个get方法,第一个是hello,直接使用Mono.just返回一个Mono。


第二个方法是hellos,通过Flux的一系列操作,最后返回一个Flux对象。


有了Mono对象,我们怎么取出里面的数据呢?


public class WelcomeWebClient {
  private WebClient client = WebClient.create("http://localhost:8080");
  private final 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来获取get的结果,通过exchange将其转换为ClientResponse。


然后提供了一个getResult方法从result中获取最终的返回结果。


这里,我们先调用FlatMap对ClientResponse进行转换,然后再调用block方法,产生一个新的subscription。


最后,我们看一下Spring Boot的启动类:


@Slf4j
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        WelcomeWebClient welcomeWebClient = new WelcomeWebClient();
        log.info("react result is {}",welcomeWebClient.getResult());
    }
}


编程方式使用webFlux



刚刚的注解方式其实跟我们常用的Spring MVC基本上是一样的。


接下来,我们看一下,如果是以编程的方式来编写上面的逻辑应该怎么处理。


首先,我们定义一个处理hello请求的处理器:


@Component
public class WelcomeHandler {
  public Mono<ServerResponse> hello(ServerRequest request) {
    return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
      .body(BodyInserters.fromValue("www.flydean.com!"));
  }
}


和普通的处理一样,我们需要返回一个Mono对象。


注意,这里是ServerRequest,因为WebFlux中没有Servlet。


有了处理器,我们需要写一个Router来配置路由:


@Configuration
public class WelcomeRouter {
  @Bean
  public RouterFunction<ServerResponse> route(WelcomeHandler welcomeHandler) {
    return RouterFunctions
      .route(RequestPredicates.GET("/hello").
          and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), welcomeHandler::hello);
  }
}


上面的代码将/hello和welcomeHandler::hello进行了绑定。


WelcomeWebClient和Application是和第一种方式是一样的。


public class WelcomeWebClient {
  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();
  }
}


public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        WelcomeWebClient welcomeWebClient = new WelcomeWebClient();
        log.info("react result is {}",welcomeWebClient.getResult());
    }
}


Spring WebFlux的测试



怎么对webFlux代码进行测试呢?


本质上是和WelcomeWebClient的实现是一样的,我们去请求对应的对象,然后检测其返回值,最后判断返回值是否我们所期待的内容。


如下所示:


@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WelcomeRouterTest {
    @Autowired
    private WebTestClient webTestClient;
    @Test
    public void testHello() {
        webTestClient
                .get().uri("/hello")
                .accept(MediaType.TEXT_PLAIN)
                .exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("www.flydean.com!");
    }
}


总结



webFlux使用了Reactor作为底层的实现,和通常我们习惯的web请求方式是有很大不同的,但是通过我们的Spring框架,可以尽量保证原有的代码编写风格和习惯。


只需要在个别部分做微调。希望大家能够通过这个简单的例子,熟悉Reactive的基本编码实现。


本文的例子可以参考:springboot-reactive-web

相关文章
|
前端开发 算法 API
构建高性能图像处理Web应用:Next.js与TailwindCSS实践
本文分享了构建在线图像黑白转换工具的技术实践,涵盖技术栈选择、架构设计与性能优化。项目采用Next.js提供优秀的SSR性能和SEO支持,TailwindCSS加速UI开发,WebAssembly实现高性能图像处理算法。通过渐进式处理、WebWorker隔离及内存管理等策略,解决大图像处理性能瓶颈,并确保跨浏览器兼容性和移动设备优化。实际应用案例展示了其即时处理、高质量输出和客户端隐私保护等特点。未来计划引入WebGPU加速、AI增强等功能,进一步提升用户体验。此技术栈为Web图像处理应用提供了高效可行的解决方案。
|
缓存 前端开发 应用服务中间件
Web端实时通信技术SSE在携程机票业务中的实践应用
本文介绍了携程机票前端基于Server-Sent Events(SSE)实现服务端推送的企业级全链路通用技术解决方案。文章深入探讨了 SSE 技术在应用过程中包括方案对比、技术选型、链路层优化以及实际效果等多维度的技术细节,为类似使用场景提供普适性参考和借鉴。该方案设计目标是实现通用性,适用于各种网络架构和业务场景。
440 1
|
缓存 前端开发 应用服务中间件
Web端实时通信技术SSE在携程机票业务中的实践应用
本文介绍了携程机票前端基于Server-Sent Events(SSE)实现服务端推送的企业级全链路通用技术解决方案。文章深入探讨了 SSE 技术在应用过程中包括方案对比、技术选型、链路层优化以及实际效果等多维度的技术细节,为类似使用场景提供普适性参考和借鉴。
529 7
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
813 1
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
1706 8
|
Web App开发 编解码 vr&ar
使用Web浏览器访问UE应用的最佳实践
在3D/XR应用开发中,尤其是基于UE(虚幻引擎)开发的高精度场景,传统终端因硬件局限难以流畅运行高帧率、复杂效果的三维应用。实时云渲染技术,将渲染任务转移至云端服务器,降低终端硬件要求,确保用户获得流畅体验。具备弹性扩展、优化传输协议、跨平台支持和安全性等优势,适用于多种终端和场景,特别集成像素流送技术,帮助UE开发者实现低代码上云操作,简化部署流程,保留UE引擎的强大开发能力,确保画面精美且终端轻量化。
793 17
使用Web浏览器访问UE应用的最佳实践
|
中间件 关系型数据库 数据库
docker快速部署OS web中间件 数据库 编程应用
通过Docker,可以轻松地部署操作系统、Web中间件、数据库和编程应用。本文详细介绍了使用Docker部署这些组件的基本步骤和命令,展示了如何通过Docker Compose编排多容器应用。希望本文能帮助开发者更高效地使用Docker进行应用部署和管理。
477 19
|
弹性计算 Java 关系型数据库
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
417 2
Web应用上云经典架构实践教学
|
Java 应用服务中间件 API
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
494 5
|
9月前
|
JavaScript Java 关系型数据库
基于springboot的项目管理系统
本文探讨项目管理系统在现代企业中的应用与实现,分析其研究背景、意义及现状,阐述基于SSM、Java、MySQL和Vue等技术构建系统的关键方法,展现其在提升管理效率、协同水平与风险管控方面的价值。