快速上手Spring WebFlux框架

简介: 本文主要介绍基于SpringBoot如何快速上手使用SpringFlux框架开发WEB网站。 Spring 5.0在原有的Spring MVC Stack(又称Servlet Stack)以外,又引入了新的WEB开发技术栈——Spring Flux Stack(又称Reactive Stack),以满足不同的应用程序及开发团队的需求。

一、前言

本文主要介绍基于SpringBoot如何快速上手使用SpringFlux框架开发WEB网站。

Spring 5.0在原有的Spring MVC Stack(又称Servlet Stack)以外,又引入了新的WEB开发技术栈——Spring Flux Stack(又称Reactive Stack),以满足不同的应用程序及开发团队的需求。

开发者一直在寻找最适合他们的应用程序的运行时、编程框架及架构。比如,有些用例最适合采用基于同步阻塞IO架构的技术栈,而另一些用例可能更适合于基于Reactive Streams响应式编程原则构建的异步的、非阻塞的技术栈。

后续将有系列文章深入介绍SpringFlux所采用的响应式编程原则及其代表实现ProjectReactor,希望通过系列文章的介绍,让广大读者能够在逐步使用SpringFlux的过程中,理解响应式编程原理及实现,进而能够对项目应该选择SpringMVC还是SpringWebFlux形成自己的判断标准。

二、快速上手

1、创建项目

打开 http://start.spring.io,来初始化一个Spring WebFlux项目吧。左侧一列是Project Metadata,填上你的group名(我们使用net.yesdata吧),还有Artifact名(默认是demo);然后右侧一列是Dependencies(依赖),我们输入"reactive web",在得到的下拉框中选择"Reacive Web",然后下方"Selected Dependencies"处会显示我们选中的"Reactive Web"。然后点击"Generate Project",浏览器会下载创建好的Spring Boot项目。加压后用你喜欢的IDE(Eclipse或者IntelliJ IDEA等)。

通过start.spring.io创建reactive栈的项目

2、增加一个Controller

如果你熟悉Spring MVC,你一定对@Controller注解不陌生。即使不熟悉也没关系,我会简单介绍一下。
Spring WebFlux带有两种特征,一种是函数式的(Functional),另一种是基于注解的(annotation-based)。函数式编程不太适合快速上手,我们先选择基于注解。类似于Spring MVC模型,Spring WebFlux模型也使用@Controller注解,以及@RestController注解。

用IDE打开项目后,追加一个类:SampleController
然后增加如下代码:

@RestController
@RequestMapping("/")
public class SampleController {

    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}

运行后,用浏览器访问:http://localhost:8080/hello,将会在浏览器上看到"hello"字样。

增加SampleController

SampleController执行结果

怎么样,是不是很简单。

3、增加一个WebFilter

增加一个Filter试试看。在Spring WebFlux框架下,增加Filter是通过实现WebFilter接口实现的。

@Component
public class FirstWebFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
        serverWebExchange.getAttributes().put("User", "jerry");
        return webFilterChain.filter(serverWebExchange);
    }
}

三、深入了解一下SpringBoot启动Spring WebFlux的过程

对于已经笔记熟悉Spring MVC框架的开发人员来说,快速上手无法满足欲望。必须了解其背后的机制原理等,方能有知己知彼的感觉。接下来稍微探讨以下SpringBoot启动Spring WebFlux的过程。尚不太熟悉Spring MVC框架的开发人员也可以阅读一下本章内容,或许对更好地使用Spring WebFlux框架有帮助。

1、准备工作

你需要从Gitubhttps://github.com/spring-projects/spring-framework下载Spring WebFlux的源码,以便进行后续分析。

2、@EnableWebFlux

回顾一下通过http://start.spring.io创建项目中,DemoApplication启动类的注解中,有一个注解是:@EnableWebFlux。SpringBoot就是通过这个注解,来启动Spring WebFlux的。

@EnableWebFlux
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

再看一下EnableWebFlux的定义(可以到SpringWebFlux源码中找到),如下,我们注意到它引入了DelegatingWebFluxConfiguration类。看来秘密会藏在DelegatingWebFluxConfiguration类里呢。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebFluxConfiguration.class)
public @interface EnableWebFlux {
}

打开DelegatingWebFluxConfiguration.java文件(可以到SpringWebFlux源码中找到),然后你我们发现它的父类是WebFluxConfigurationSupport类。我们先来看看这个父类。

@Configuration
public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport {
......
}

下面是父类WebFluxConfigurationSupport实现的代码片段。我们注意到,它向Spring Bean容器中,注入了两个Bean:webHandler和requestMappingHandlerMapping(实际上还注入了其它若干个Bean,不过我们暂时只关注这两个吧)。

名为"webHandler"的Bean的类型是DispatcherHandler,顾名思义是分发器,分发请求给各个处理单元。
名为"requestMappingHandlerMapping"的Bean的类型是RequestMappingHandlerMapping,它的根本是实现了HandlerMapping接口。HandlerMapping的作用是将请求映射到Handler上,比如把某个请求路径映射到某个Controller上。

关于DispatcherHandler和HandlerMapping,后面章节继续深入讲解。

public class WebFluxConfigurationSupport implements ApplicationContextAware {
    @Bean
    public DispatcherHandler webHandler() {
        return new DispatcherHandler();
    }
    
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
        mapping.setOrder(0);
        mapping.setContentTypeResolver(webFluxContentTypeResolver());
        mapping.setCorsConfigurations(getCorsConfigurations());

        PathMatchConfigurer configurer = getPathMatchConfigurer();
        Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
        if (useTrailingSlashMatch != null) {
            mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
        }
        Boolean useCaseSensitiveMatch = configurer.isUseCaseSensitiveMatch();
        if (useCaseSensitiveMatch != null) {
            mapping.setUseCaseSensitiveMatch(useCaseSensitiveMatch);
        }
        Map<String, Predicate<Class<?>>> pathPrefixes = configurer.getPathPrefixes();
        if (pathPrefixes != null) {
            mapping.setPathPrefixes(pathPrefixes);
        }

        return mapping;
    }
}

2、DispatcherHandler

DispatcherHandler将自身作为Bean注册到Spring的Bean容器中,它与WebFilter、WebExceptionHandler等一起,组成处理链。

DispatcherHandler会从Spring Configuration中探寻到它需要的组件,主要是以下三类:

public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    ...
    private List<HandlerMapping> handlerMappings;
    private List<HandlerAdapter> handlerAdapters;
    private List<HandlerResultHandler> resultHandlers;
    ...
}
  • HandlerMapping

    • 映射Request到Handler
    • HandlerMapping的默认实现是RequestMappingHandlerMapping,用于@RequestMapping所标记的方法;RouterFunctionMapping用于函数式端点的路由;SimpleUrlHandlerMapping用于显式注册的URL模式与WebHandler
  • HandlerAdaptor

    • 帮助DispatcherHandler调用Request所映射的Handler
    • HandlerAdaptor的主要作用是将DispatcherHandler从调用具体Handler的细节中解放出来
  • HandlerResultHandler

    • 处理Handler的结果并终结Response
    • 调用具体的Handler的返回结果是包装在HandlerResult中的,HandlerResultHandler负责处理HandlerResult。比如ResponseBodyResultHandler负责处理@ResponseBody标记的方法的返回值

示意图如下:

DispatcherHandler
  |
  |-->HandlerMapping
  |-->HandlerAdaptor
  |-->HandlerResultHandler

DispatcherHandler的核心方法是:

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
    if (this.handlerMappings == null) {
        return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);
    }
    return Flux.fromIterable(this.handlerMappings)
            .concatMap(mapping -> mapping.getHandler(exchange))
            .next()
            .switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))
            .flatMap(handler -> invokeHandler(exchange, handler))
            .flatMap(result -> handleResult(exchange, result));
}

该方法道出了DispatcherHandler处理请求的套路

  • 先通过HandlerMapping找到Request的专用Handler,具体的代码片段是
concatMap(mapping -> mapping.getHandler(exchange))
  • 再通过HandlerAdaptor执行这个具体的Handler,具体的代码片段是
flatMap(handler -> invokeHandler(exchange, handler))
  • 最后通过HandlerResultHandler处理Handler返回的结果,具体的代码片段是
flatMap(result -> handleResult(exchange, result))

可能你有疑问,这个方法里Request在哪呢?藏在"ServerWebExchange exchange"里了,关于ServerWebExchange又其它文章进一步介绍,这儿就不作详细说明了。

3、HandlerMapping

DispatcherHandler套路中,处理Request的第一环节就是使用HandlerMapping。常见的HandlerMapping有三种:RequestMappingHandlerMapping、RouterFunctionMapping、SimpleUrlHandlerMapping

RequestMappingHandlerMapping是默认的,是否还记得DispatcherHandler中有发布一个Bean名为"requestMappingHandlerMapping"?它承担了映射Request与annotation-based Handler之间的关系。

由于我们习惯于使用@Controller、@RestController、@RequestMapping之类的注解来开发WEB项目,所以非常依赖RequestMappingHandlerMapping。我们接下来就谈谈RequestMappingHandlerMapping

3-1、RequestMappingHandlerMapping的类层级

1层:AbstractHandlerMapping implements HandlerMapping, Ordered, BeanNameAware

  ^
  |

2层:AbstractHandlerMethodMapping implements InitializingBean

  ^
  |

3层:RequestMappingInfoHandlerMapping

  ^
  |

4层:RequestMappingHandlerMapping implements EmbeddedValueResolverAware

3-2、扫描可用handler

大家注意到,第2层实现了InitializingBean接口,实现了该接口的类有机会在BeanFactory设置好它的所有属性后通过调用

void afterPropertiesSet()

方法通知它。我们来看看第2层的对该方法的实现吧。

@Override
public void afterPropertiesSet() {

    initHandlerMethods();
    
    // Total includes detected mappings + explicit registrations via registerMapping..
    ...
}

篇幅原因,这儿不细究方法中所调用的

initHandlerMethods();

的细节了 —— 实际上这里面是扫描所有@Controller注解的类中的@RequestMapping及其变体所修饰的方法,即最终会处理Request的Handler,并缓存起来,以便后续进一步执行。

3-3、与DispatcherHandler相互配合

DispatcherHandler会调用MappingHandler的

Mono<Object> getHandler(ServerWebExchange exchange)

方法,选择处理这个请求交的具体的Handler。

四、总结

Spring WebFlux模型的使用非常简单,尤其是对于熟悉Spring MVC模型的开发人员来说,无缝切换。使用Spring Boot框架开发时,使用@Controller、@RestController、@RequestMapping等注解,实现处理Request的Handler尤其方便。

原文:http://www.yesdata.net/2018/11/20/spring-flux/

相关文章
|
12月前
|
安全 Java Ruby
我尝试了所有后端框架 — — 这就是为什么只有 Spring Boot 幸存下来
作者回顾后端开发历程,指出多数框架在生产环境中难堪重负。相比之下,Spring Boot凭借内置安全、稳定扩展、完善生态和企业级支持,成为构建高可用系统的首选,真正经受住了时间与规模的考验。
793 2
|
XML JSON Java
Spring框架中常见注解的使用规则与最佳实践
本文介绍了Spring框架中常见注解的使用规则与最佳实践,重点对比了URL参数与表单参数的区别,并详细说明了@RequestParam、@PathVariable、@RequestBody等注解的应用场景。同时通过表格和案例分析,帮助开发者正确选择参数绑定方式,避免常见误区,提升代码的可读性与安全性。
|
前端开发 Java API
利用 Spring WebFlux 技术打造高效非阻塞 API 的完整开发方案与实践技巧
本文介绍了如何使用Spring WebFlux构建高效、可扩展的非阻塞API,涵盖响应式编程核心概念、技术方案设计及具体实现示例,适用于高并发场景下的API开发。
820 0
|
11月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
11月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
905 8
|
监控 Kubernetes Cloud Native
Spring Batch 批处理框架技术详解与实践指南
本文档全面介绍 Spring Batch 批处理框架的核心架构、关键组件和实际应用场景。作为 Spring 生态系统中专门处理大规模数据批处理的框架,Spring Batch 为企业级批处理作业提供了可靠的解决方案。本文将深入探讨其作业流程、组件模型、错误处理机制、性能优化策略以及与现代云原生环境的集成方式,帮助开发者构建高效、稳定的批处理系统。
958 1
|
监控 Java API
Spring WebFlux 响应式编程技术详解与实践指南
本文档全面介绍 Spring WebFlux 响应式编程框架的核心概念、架构设计和实际应用。作为 Spring 5 引入的革命性特性,WebFlux 提供了完全的响应式、非阻塞的 Web 开发栈,能够显著提升系统的并发处理能力和资源利用率。本文将深入探讨 Reactor 编程模型、响应式流规范、WebFlux 核心组件以及在实际项目中的最佳实践,帮助开发者构建高性能的响应式应用系统。
1556 0
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
1139 1
|
缓存 安全 Java
Spring 框架核心原理与实践解析
本文详解 Spring 框架核心知识,包括 IOC(容器管理对象)与 DI(容器注入依赖),以及通过注解(如 @Service、@Autowired)声明 Bean 和注入依赖的方式。阐述了 Bean 的线程安全(默认单例可能有安全问题,需业务避免共享状态或设为 prototype)、作用域(@Scope 注解,常用 singleton、prototype 等)及完整生命周期(实例化、依赖注入、初始化、销毁等步骤)。 解析了循环依赖的解决机制(三级缓存)、AOP 的概念(公共逻辑抽为切面)、底层动态代理(JDK 与 Cglib 的区别)及项目应用(如日志记录)。介绍了事务的实现(基于 AOP
534 0
|
Cloud Native Java API
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
1831 0