doc: 阅读webflux文档
This commit is contained in:
@@ -41,6 +41,13 @@
|
||||
- [Server Request](#server-request)
|
||||
- [ServerResponse](#serverresponse)
|
||||
- [Handler Class](#handler-class)
|
||||
- [Validation](#validation)
|
||||
- [RouterFunction](#routerfunction)
|
||||
- [Predicates](#predicates)
|
||||
- [Routes](#routes)
|
||||
- [Nested Routes](#nested-routes)
|
||||
- [Resource Redirect](#resource-redirect)
|
||||
- [Filter Handler Functions](#filter-handler-functions)
|
||||
|
||||
|
||||
# Spring Webflux
|
||||
@@ -625,6 +632,155 @@ HandlerFunction<ServerResponse> helloWorld =
|
||||
request -> ServerResponse.ok().bodyValue("Hello World");
|
||||
```
|
||||
|
||||
### Validation
|
||||
如果想要对请求体进行校验,可以使用如下逻辑:
|
||||
```java
|
||||
public class PersonHandler {
|
||||
|
||||
private final Validator validator = new PersonValidator();
|
||||
|
||||
// ...
|
||||
|
||||
public Mono<ServerResponse> createPerson(ServerRequest request) {
|
||||
Mono<Person> person = request.bodyToMono(Person.class).doOnNext(this::validate);
|
||||
return ok().build(repository.savePerson(person));
|
||||
}
|
||||
|
||||
private void validate(Person person) {
|
||||
Errors errors = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, errors);
|
||||
if (errors.hasErrors()) {
|
||||
throw new ServerWebInputException(errors.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
### RouterFunction
|
||||
RouterFunction用于将请求路由到对应的HandlerFunction,通常情况下都通过`RouterFunctions`工具类来创建router。
|
||||
|
||||
`RouterFunctions.route()`方法提供了许多快捷创建router的方法,例如`GET(String, HandlerFunction)`等。
|
||||
|
||||
除了基于HTTP method进行映射外,router builder还提供了引入额外Predicates来进行请求路由的机制,对于每个基于http method进行路由的方法,都存在一个重载方法,用于接收predicates。
|
||||
|
||||
#### Predicates
|
||||
使用者可以编写自己的RequestPredicate,但是`RequestPredicates`工具提供了常用的实现,可以基于request path、http method、content-type等进行判断。
|
||||
|
||||
在如下示例中,展示了通过`Accept` header进行判断的示例:
|
||||
```java
|
||||
RouterFunction<ServerResponse> route = RouterFunctions.route()
|
||||
.GET("/hello-world", accept(MediaType.TEXT_PLAIN),
|
||||
request -> ServerResponse.ok().bodyValue("Hello World")).build();
|
||||
```
|
||||
|
||||
如果想要对多个predicates进行逻辑运算,可以使用如下方法:
|
||||
- `RequestPredicate.and(RequestPredicate)`:两者都满足
|
||||
- `RequestPredicate.or(RequestPredicate)`:两者任一满足
|
||||
|
||||
predicates中许多都是组合的,例如`equestPredicates.GET(String)`是由`RequestPredicates.method(HttpMethod)`和`RequestPredicates.path(String)`进行组合的。
|
||||
|
||||
在上述示例中,其实也使用到了两个predicates,builder内部使用了`RequestPredicates.GET`,调用方则指定了`accept`。
|
||||
|
||||
#### Routes
|
||||
Router function将会按顺序被调用,如果前一个route没有匹配,将会调用下一个route。
|
||||
|
||||
在使用router function builder时,所有定义的routes都被整合在一个`RouterFunction`中,并且通过`build`方法进行返回。
|
||||
|
||||
除了使用router builder之外,还可以将多个router function整合在一起:
|
||||
- 调用`RouterFunctions.route()`中的`add(RouterFunction)`方法
|
||||
- `RouterFunction.and(RouterFunction)`方法
|
||||
- and方法代表前面的方法没有匹配时,后调用后面的RouterFunction
|
||||
- `RouterFunction.andRoute(RequestPredicate, HandlerFunction) `方法
|
||||
|
||||
使用示例如下所示:
|
||||
```java
|
||||
PersonRepository repository = ...
|
||||
PersonHandler handler = new PersonHandler(repository);
|
||||
|
||||
RouterFunction<ServerResponse> otherRoute = ...
|
||||
|
||||
RouterFunction<ServerResponse> route = route()
|
||||
.GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson)
|
||||
.GET("/person", accept(APPLICATION_JSON), handler::listPeople)
|
||||
.POST("/person", handler::createPerson)
|
||||
.add(otherRoute)
|
||||
.build();
|
||||
```
|
||||
|
||||
#### Nested Routes
|
||||
通常情况下,很有可能许多路由都包含相同的predicate,例如共享路径。
|
||||
|
||||
如下示例展示了3个routes共用`/preson`路径的场景:
|
||||
```java
|
||||
RouterFunction<ServerResponse> route = route()
|
||||
.path("/person", builder -> builder
|
||||
.GET("/{id}", accept(APPLICATION_JSON), handler::getPerson)
|
||||
.GET(accept(APPLICATION_JSON), handler::listPeople)
|
||||
.POST(handler::createPerson))
|
||||
.build();
|
||||
```
|
||||
在上述示例中,route1和route2都接收json格式参数,故而还能继续嵌套,示例如下:
|
||||
```java
|
||||
RouterFunction<ServerResponse> route = route()
|
||||
.path("/person", b1 -> b1
|
||||
.nest(accept(APPLICATION_JSON), b2 -> b2
|
||||
.GET("/{id}", handler::getPerson)
|
||||
.GET(handler::listPeople))
|
||||
.POST(handler::createPerson))
|
||||
.build();
|
||||
```
|
||||
|
||||
#### Resource Redirect
|
||||
RounterFunction的Builder支持对resource进行重定向,示例如下:
|
||||
```java
|
||||
Resource location = new FileUrlResource("public-resources/");
|
||||
RouterFunction<ServerResponse> resources = RouterFunctions.resources("/resources/**", location);
|
||||
```
|
||||
### Filter Handler Functions
|
||||
可以针对routing function builder添加filter,builder支持如下方法:
|
||||
- before
|
||||
- after
|
||||
- filter
|
||||
|
||||
对builder添加的filter,会应用到buidler中所有的routes,示例如下所示:
|
||||
```java
|
||||
RouterFunction<ServerResponse> route = route()
|
||||
.path("/person", b1 -> b1
|
||||
.nest(accept(APPLICATION_JSON), b2 -> b2
|
||||
.GET("/{id}", handler::getPerson)
|
||||
.GET(handler::listPeople)
|
||||
.before(request -> ServerRequest.from(request)
|
||||
.header("X-RequestHeader", "Value")
|
||||
.build()))
|
||||
.POST(handler::createPerson))
|
||||
.after((request, response) -> logResponse(response))
|
||||
.build();
|
||||
```
|
||||
上述示例中,filter的范围如下:
|
||||
- `before`:before只会应用到GET请求
|
||||
- `after`:after会应用到所有请求,包括nested routes
|
||||
|
||||
对于`builder.filter`方法,其接收`HandlerFilterFunction`类型的参数,使用示例如下:
|
||||
```java
|
||||
SecurityManager securityManager = ...
|
||||
|
||||
RouterFunction<ServerResponse> route = route()
|
||||
.path("/person", b1 -> b1
|
||||
.nest(accept(APPLICATION_JSON), b2 -> b2
|
||||
.GET("/{id}", handler::getPerson)
|
||||
.GET(handler::listPeople))
|
||||
.POST(handler::createPerson))
|
||||
.filter((request, next) -> {
|
||||
if (securityManager.allowAccessTo(request.path())) {
|
||||
return next.handle(request);
|
||||
}
|
||||
else {
|
||||
return ServerResponse.status(UNAUTHORIZED).build();
|
||||
}
|
||||
})
|
||||
.build();
|
||||
```
|
||||
除了可以向builder添加filter外,还可以向已经存在的router function中添加filter,通过`RouterFunction.filter(HandlerFilterFunction)`方法。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user