1. 前言

从一开始学习 Netty 到 rxjava、Rector,再到 java8 的 CompletableFuture,就深深的为响应式编程着迷,这种区别于传统的顺序式编程,没准未来能在编程世界开辟一片天地呢!

然后接触到了 WebFlux 框架,也是充满了浓厚的兴趣,想好好琢磨一番,奈何中文资料实在太少,就打起了英文文档的主意,可惜英文水平实在捉急,总是看下一句,忘了上一句。诶,要不咱一句句翻译出来吧,这样读起来就通顺了,顺便可以造福下后来学习者(想着翻译的东西要被人看,也是一份坚持的动力)。

翻译并没有逐字逐句去纠结,力求语义通顺,有理解错误的地方,还麻烦大家指出,一起学习探讨。另外,文中还补充了一些自己练习的 demo。

原文链接:https://docs.spring.io/spring-boot/docs/2.1.7.RELEASE/reference/htmlsingle/#boot-features-webflux

github 练习 demo:https://github.com/JMCuixy/webflux

tips:翻译是一项提高英语和学习技能一举两得的事呀!

2. WebFlux 简介

Spring WebFlux 是 Spring 5.0 引入的新的响应式框架,区别于 Spring MVC,它不需要依赖Servlet API,它是完全异步非阻塞的,并且基于 Reactor 来实现响应式流规范。

Spring WebFlux 有两种表现形式:基于配置和基于注释。基于注释的实现方式非常类似于 SpringMVC 模型,如以下实例:

@RestController
@RequestMapping("/users")
public class MyRestController { @GetMapping("/\{user}")
public Mono<User> getUser(@PathVariable Long user) {
// ...
} @GetMapping("/\{user}/customers")
public Flux<Customer> getUserCustomers(@PathVariable Long user) {
// ...
} @DeleteMapping("/\{user}")
public Mono<User> deleteUser(@PathVariable Long user) {
// ...
} }

基于配置的实现方式,把路由和具体请求逻辑分离开,如以下实例:

@Configuration
public class RoutingConfiguration { @Bean
public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
return route(GET("/\{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
.andRoute(GET("/\{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
.andRoute(DELETE("/\{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
} } @Component
public class UserHandler { public Mono<ServerResponse> getUser(ServerRequest request) {
// ...
} public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
// ...
} public Mono<ServerResponse> deleteUser(ServerRequest request) {
// ...
}
}

WebFlux 是 Spring 框架的一部分,其参考文档中提供了详细信息。

你可以定义任意数量的 RouterFunction Bean,以对你的路由进行归纳整理。当然,你也可以针对多个 RouterFunction 设置优先级(@Order 注解)。

开始一个 WebFlux 项目,首先,需要将 spring-boot-starter-webflux 模块引入你的项目。值得注意的是,如果你同时引入了 spring-boot-starter-web 和 spring-boot-starter-webflux 模块会导致 Spring Boot 自动配置Spring MVC,而不是 WebFlux。因为许多 Spring 开发人员引入 spring-boot-starter-webflux ,仅仅是为了使用它的响应式编程(这个理由也是绝了),当然你也可以强制把你的项目配置成 WebFlux:

SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)

3. 自动配置

Spring Boot 为 Spring WebFlux 提供的自动配置基本能适用于大多数应用。

Spring Boot 的提供的自动配置主要做了以下两个工作:

  • 为 HttpMessageReader 和 HttpMessageWriter 实例配置 HTTP 编解码器
  • 支持服务静态资源映射,包括对 WebJars 资源的支持

如果你想要保持 Spring Boot WebFlux 的自动配置功能,并且想添加额外的 WebFlux 配置项,你可以自定义 @Configuration 配置类,但不要添加 @EnableWebFlux 注解。

如果你想要完全控制 WebFlux,你可以定义@Configuration 配置类,并且添加 @EnableWebFlux. 注解。

4. HttpMessageReaders 和 HttpMessageWriters 的 HTTP 编解码器

Spring WebFlux 使用 HttpMessageReader 和 HttpMessageWriter 接口来转换 HTTP 请求和响应,可以通过 CodecConfigurer 得到它们的默认配置:

public interface CodecConfigurer {
... List<HttpMessageReader<?>> getReaders(); List<HttpMessageWriter<?>> getWriters();
...
}

Spring Boot 提供了 CodecCustomizer 接口,允许你进一步定制编解码器,通过其 customize() 方法可以获取到 CodecConfigurer 对象,从而可以注册新的编解码工具,或对现有的编解码工具进行替换等。如以下实例:

import org.springframework.boot.web.codec.CodecCustomizer;

@Configuration
public class MyConfiguration { @Bean
public CodecCustomizer myCodecCustomizer() {
return codecConfigurer -> {
// ...
}
} }

5. 静态资源

Spring Boot 默认从类路径的以下目录(/static、 /public 、/resources 、/META-INF/resources)加载静态资源,当然,你可以自定义配置类实现 WebFluxConfigurer 并重写 addResourceHandlers 方法来修改默认资源路径:

@Configuration
public class MyWebFluxConfigurer implements WebFluxConfigurer { @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// do more
}
}

Spring Boot 默认将静态资源映射在 /** 的路径下,当然,你可以通过修改 spring.webflux.static-path-pattern 属性来调整默认映射,例如,将所有资源映射到 /resources/** 路径 ,可以通过以下方式实现:

spring.webflux.static-path-pattern=/resources/**

你也可以通过设置 spring.resources.static-locations 属性值来自定义资源目录,如果你这样做了,默认的欢迎页面检测也将会切换到你设置的资源目录。因此,在你的资源目录中,只要有一个 index.html 页面,都将会成为你的应用主页。

除了前面介绍的标准静态资源外,还有一种特殊的情况,那就是 webjars 内容。如果静态资源被打包成了 webjars 的格式,那么访问这些资源的路径就变成了 /webjars/** 。

tips:Spring WebFlux 应用程序不严格依赖 Servlet API,因此不能将它们部署为 war 文件,也不使用 src/main/webapp 目录。

6. 模板引擎

Spring WebFlux 除了提供 REST web 服务外,还支持渲染动态 HTML 内容,Spring WebFlux 支持一系列模板引擎,包括 Thymeleaf、FreeMarker 和 Mustache。

Spring Boot 为以下的模板引擎提供了自动配置的支持:

当你使用了其中某个模板引擎,并选择了 Spring Boot 自动配置,你需要将你的模板文件放在 src/main/resources/templates 目录下,以便被 Spring Boot 发现。

7. 异常处理

Spring Boot 提供了一个 WebExceptionHandler 用来处理所有错误,WebExceptionHandler 执行通常被认为是处理链中的最后一步,仅位于 WebFlux 提供服务之前。对于机器端,它通常是一个 JSON 响应,包含了HTTP 状态码、错误信息等;对于浏览器端,它通常是一个 “whitelabel” HTML 错误页面,页面渲染了相同的错误信息。当然,你也可以提供自定义的 HTML 模板来展示错误信息(下文会说到)。

首先,定制此功能通常涉及利用现有机制,但要替换或增加错误内容,你可以添加 ErrorAttributes 类型的 Bean。

若要更改错误处理行为,可以实现 ErrorWebExceptionHandler 并注册该类型的 bean 定义,但是 WebExceptionHandler 级别很低。因此 Spring Boot 还提供了一种方便的方式,即继承 AbstractErrorWebExceptionHandler,让你可以通过 WebFlux 的方式处理错误,如以下示例所示(这个配置贼复杂,建议还是乖乖的用默认配置吧):

public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

	// Define constructor here

	@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { return RouterFunctions
.route(aPredicate, aHandler)
.andRoute(anotherPredicate, anotherHandler);
} }

如果你想要为给定的错误码展示自定义的 HTML 错误页面,你可以在 /error 目录下添加一个错误页面文件。可以是静态HTML(即添加到任意静态资源文件夹下),也可以使用模板构建,文件名应为确切的状态码或系列掩码。

例如,要映射 404 错误码到静态 HTML 文件,您的文件夹结构如下:

src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>

使用 Mustache 模板对 5xx 错误码作映射,您的文件夹结构如下:

src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.mustache
+- <other templates>

8. 过滤器

Spring WebFlux 提供了一个 WebFilter 接口,用来对 HTTP 请求-响应路由进行过滤,在应用程序上下文中找到的 WebFilter bean 将自动用于过滤每个路由!以下是一个简单鉴权的过滤器 demo — 对于 没有 token 参数的请求返回 401 错误:

@Component
public class CustomWebFilter implements WebFilter { @Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
if (queryParams == null || StringUtils.isEmpty(queryParams.getFirst("token"))) {
Map<String, String> resultMap = new HashMap<>();
resultMap.put("code", "401");
resultMap.put("msg", "非法请求");
byte[] datas = new byte[0];
try {
datas = new ObjectMapper().writeValueAsBytes(resultMap);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
ServerHttpResponse response = exchange.getResponse();
DataBuffer buffer = response.bufferFactory().wrap(datas);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
} return chain.filter(exchange).then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
//Manipulate the response in some way
}));
}
}

可以通过实现 Ordered 接口或使用 @Order 注释来设置过滤器的执行顺序(执行顺序是从小到大执行,较高的值被解释为较低的优先级)。Spring Boot 的自动配置功能已经为你提供了一些内置的过滤器,如下是它们的执行顺序:

Web Filter Order
MetricsWebFilter Ordered.HIGHEST_PRECEDENCE + 1
WebFilterChainProxy (Spring Security) -100
HttpTraceWebFilter Ordered.LOWEST_PRECEDENCE - 10

Spring Boot WebFlux 2.1.7 中文翻译文档的更多相关文章

  1. 【转】XMPP_3920_最靠谱的中文翻译文档

    CHENYILONG Blog XMPP_3920_最靠谱的中文翻译文档 Fullscreen © chenyilong. Powered by Postach.io Blog

  2. Spring Boot WebFlux 快速入门实践

    02:WebFlux 快速入门实践 Spring Boot 2.0 spring.io 官网有句醒目的话是: BUILD ANYTHING WITH SPRING BOOT Spring Boot ( ...

  3. Spring Boot WebFlux 增删改查完整实战 demo

    03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello .这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD ...

  4. Spring Boot (十四): 响应式编程以及 Spring Boot Webflux 快速入门

    1. 什么是响应式编程 在计算机中,响应式编程或反应式编程(英语:Reactive programming)是一种面向数据流和变化传播的编程范式.这意味着可以在编程语言中很方便地表达静态或动态的数据流 ...

  5. Spring Boot WebFlux 集成 Mongodb 数据源操作

    WebFlux 整合 Mongodb 前言 上一讲用 Map 数据结构内存式存储了数据.这样数据就不会持久化,本文我们用 MongoDB 来实现 WebFlux 对数据源的操作. 什么是 MongoD ...

  6. spring boot: 通过filter过滤器实现中文的简体繁体字符集转换(spring boot 2.3.1)

    一,为什么要使用filter来实现简繁体转换? 项目中有时会有同时支持简体和繁体两种字符集的要求, 或者搜索引擎有支持繁体输入字符的需求. 针对繁体字符的显示, 我们通常会在数据库和模板.文案配置中默 ...

  7. Spring Boot配置文件规则以及使用方法官方文档查找以及Spring项目的官方文档查找方法

    比如要使用Spring Boot实现一个功能,最直接的方式是Google,但是往往搜索出来的都比较乱,关键是乱在不同的版本上,比如1.x版本和2.x版本的配置是不一样的.最明显区别是在使用Thymel ...

  8. Spring Boot中使用Swagger2自动构建API文档

    由于Spring Boot能够快速开发.便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API.而我们构建RESTful API的目的通常都是由于多终端的原因,这 ...

  9. Spring Boot中使用Swagger2构建RESTful API文档

    在开发rest api的时候,为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题: 1.由于接口众多,并且细 ...

随机推荐

  1. FIT文件CRC校验

    校验FIT文件CRC代码做个记录,分为两步先校验头部然后再校验整个FIT文件.校验头部不是必需的看个人需要吧.为了偷懒使用Okio库,还有计算CRC的时候用的Garmin的FitSDK. public ...

  2. 【SQL server基础】获取当前时间并固定格式

    Select CONVERT(varchar(), GETDATE(), ): // Select CONVERT(varchar(), GETDATE(), ): Select CONVERT(va ...

  3. How to setup Electrum testnet mode and get BTC test coins

    For some reason we need to use BTC test coins, but how to set up the Bitcoin testnet wallet and get ...

  4. Kubernetes 系列(二):Deployment 扩容

    (1)首先我们创建一个nginx的Deployment,采用官方的yaml: kubectl create -f https://kubernetes.io/docs/user-guide/nginx ...

  5. Scala和Java混合项目搭建:(Eclipse)

     Scala和Java混合项目搭建:(Eclipse)  项目结构: pom.xml: <project xmlns="http://maven.apache.org/POM/4.0. ...

  6. tiki-graph_formula.php代码执行漏洞复现(或许??)

    1.不知道从哪里翻出来的虚拟机镜像(不知道甚么时候出现在磁盘里面的) 打开配置一下是tikiwiki这个东西 2.遇到陌生的玩意总是忍不住好奇心的,打开nikto扫描一下,发现有些奇怪的东西 本来没抱 ...

  7. [开源]如何使用goapp写你的后台管理系统_golang

    简析 基于 Gin + GORM + Casbin + vue-element-admin 实现的权限管理系统. 基于Casbin 实现RBAC权限管理. 前端实现: vue-element-admi ...

  8. Spring Cloud Feign 总结问题,注意点,性能调优,切换okhttp3

    ### Feign常见问题总结 **FeignClient接口如使用`@PathVariable` ,必须指定value属性** ```java //在一些早期版本中, @PathVariable(& ...

  9. Lab_0操作系统实验准备(全)

    一.实验介绍 实验目的: 知识储备: 二.相关下载 1.下载镜像文件 这个镜像文件是vdi类型的,只能用visualbox下载 链接:https://pan.baidu.com/s/1L7WX6ju4 ...

  10. 我在用的翻译软件 -> 微软翻译+网易有道词典+谷歌翻译

    Windows网页翻译 因为微软翻译相对来说翻译网页更为准确,我也喜欢用谷歌的Chrome浏览器,但是我没找到微软翻译的扩展,这里只能放弃 这个需要配合Microsoft Edge浏览器进行使用,也是 ...