当 Spring 5 稳定时,我想使用RouteFunction
而不是 @RestController。定义一个HandlerFunction来处理请求,然后声明一个RouteFunction
将请求映射到HandlerFunction:
public Mono<ServerResponse> get(ServerRequest req) {
return this.posts
.findById(req.pathVariable("id"))
.flatMap((post) -> ServerResponse.ok().body(Mono.just(post), Post.class))
.switchIfEmpty(ServerResponse.notFound().build());
}
在此处查看完整的示例代码。
Kotlin 版本,定义一个处理请求的函数,用于RouteFunctionDSL
将传入的请求映射到 HandlerFunction:
fun get(req: ServerRequest): Mono<ServerResponse> {
return this.posts.findById(req.pathVariable("id"))
.flatMap { post -> ok().body(Mono.just(post), Post::class.java) }
.switchIfEmpty(notFound().build())
}
它可以是一个表达式,例如:
fun get(req: ServerRequest): Mono<ServerResponse> = this.posts.findById(req.pathVariable("id"))
.flatMap { post -> ok().body(Mono.just(post), Post::class.java) }
.switchIfEmpty(notFound().build())
在此处查看 Kotlin DSL 的完整示例代码。
如果您更喜欢传统的控制器来公开 REST API,请尝试这种方法。
首先定义一个异常,例如。PostNotFoundException
. 然后把它扔进控制器。
@GetMapping(value = "/{id}")
public Mono<Post> get(@PathVariable(value = "id") Long id) {
return this.posts.findById(id).switchIfEmpty(Mono.error(new PostNotFoundException(id)));
}
定义一个ExceptionHandler
来处理异常,并将其注册到HttpHandler
.
@Profile("default")
@Bean
public NettyContext nettyContext(ApplicationContext context) {
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context)
.exceptionHandler(exceptionHandler())
.build();
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer httpServer = HttpServer.create("localhost", this.port);
return httpServer.newHandler(adapter).block();
}
@Bean
public WebExceptionHandler exceptionHandler() {
return (ServerWebExchange exchange, Throwable ex) -> {
if (ex instanceof PostNotFoundException) {
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().setComplete();
}
return Mono.error(ex);
};
}
在此处查看完整的代码。对于 Spring Boot 用户,请查看此示例。
更新:在最新的spring 5.2中,我找到了@RestControllerAdvice
webflux应用中控制器的通用作品。