Spring Boot WebFlux 2.1.7 中文翻译文档
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 中文翻译文档的更多相关文章
- 【转】XMPP_3920_最靠谱的中文翻译文档
CHENYILONG Blog XMPP_3920_最靠谱的中文翻译文档 Fullscreen © chenyilong. Powered by Postach.io Blog
- Spring Boot WebFlux 快速入门实践
02:WebFlux 快速入门实践 Spring Boot 2.0 spring.io 官网有句醒目的话是: BUILD ANYTHING WITH SPRING BOOT Spring Boot ( ...
- Spring Boot WebFlux 增删改查完整实战 demo
03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello .这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD ...
- Spring Boot (十四): 响应式编程以及 Spring Boot Webflux 快速入门
1. 什么是响应式编程 在计算机中,响应式编程或反应式编程(英语:Reactive programming)是一种面向数据流和变化传播的编程范式.这意味着可以在编程语言中很方便地表达静态或动态的数据流 ...
- Spring Boot WebFlux 集成 Mongodb 数据源操作
WebFlux 整合 Mongodb 前言 上一讲用 Map 数据结构内存式存储了数据.这样数据就不会持久化,本文我们用 MongoDB 来实现 WebFlux 对数据源的操作. 什么是 MongoD ...
- spring boot: 通过filter过滤器实现中文的简体繁体字符集转换(spring boot 2.3.1)
一,为什么要使用filter来实现简繁体转换? 项目中有时会有同时支持简体和繁体两种字符集的要求, 或者搜索引擎有支持繁体输入字符的需求. 针对繁体字符的显示, 我们通常会在数据库和模板.文案配置中默 ...
- Spring Boot配置文件规则以及使用方法官方文档查找以及Spring项目的官方文档查找方法
比如要使用Spring Boot实现一个功能,最直接的方式是Google,但是往往搜索出来的都比较乱,关键是乱在不同的版本上,比如1.x版本和2.x版本的配置是不一样的.最明显区别是在使用Thymel ...
- Spring Boot中使用Swagger2自动构建API文档
由于Spring Boot能够快速开发.便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API.而我们构建RESTful API的目的通常都是由于多终端的原因,这 ...
- Spring Boot中使用Swagger2构建RESTful API文档
在开发rest api的时候,为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题: 1.由于接口众多,并且细 ...
随机推荐
- 聚类算法之K-means
想想常见的分类算法有决策树.Logistic回归.SVM.贝叶斯等.分类作为一种监督学习方法,要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别与之对应.但是很多时候上述条件得不到满 ...
- Merge into 语句实例
/*Merge into 详细介绍MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句.通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,连接条件匹配 ...
- python基础(十七)
今日主要内容 正则表达式 logging模块 一.正则表达式 (一)什么是正则表达式 正则表达式的定义: 是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个& ...
- mybatis - 通用mapper
title: 玩转spring-boot-mybatis date: 2019-03-11 19:36:57 type: "mybatis" categories: mybatis ...
- ng 点击事件
执行事件获取数据 <div class="shijian"> <p>ng 事件</p> <p><button (click)= ...
- LeetCode正则表达式匹配
题目描述 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符 '*' 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 ...
- 如何编译和调试Python内核源码?
目录 写在前面 获取源代码 源代码的组织 windows下编译CPython 调试CPython 小结 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 如果对Pyth ...
- python编程基础之二十四
函数: def 函数名([参数1],[参数2],[参数3], ... ,[参数n]): 函数体代码 函数名命名规则:同标识符命名相同,但是多了一点,不要和系统函数重名,其实所有命名都是一样只要符合标识 ...
- CH3801Rainbow的信号
Description Freda发明了传呼机之后,rainbow进一步改进了传呼机发送信息所使用的信号.由于现在是数字.信息时代,rainbow发明的信号用N个自然数表示.为了避免两个人的对话被大坏 ...
- taro taroUi的H5打包后路径/修改为./
打包文件路径修改在config/index.tsx中,如下 esnextModules: ['taro-ui'],配置也需要在h5中写入并且将publicPath: './'即可,不需要在做一个h ...