How to return 404 with Spring WebFlux

前端 未结 3 1934
無奈伤痛
無奈伤痛 2021-02-15 23:47

I\'m having a controller like this one (in Kotlin):

@RestController
@RequestMapping(\"/\")
class CustomerController (private val service: CustomerService) {
             


        
3条回答
  •  一生所求
    2021-02-16 00:24

    I would like use RouteFunction instead of @RestController when Spring 5 is stable. Define a HandlerFunction to handle request, and then declare a RouteFunction to map request to the HandlerFunction:

    public Mono get(ServerRequest req) {
        return this.posts
            .findById(req.pathVariable("id"))
            .flatMap((post) -> ServerResponse.ok().body(Mono.just(post), Post.class))
            .switchIfEmpty(ServerResponse.notFound().build());
    }
    

    Check the complete example codes here.

    Kotlin version, define a function to handle request, the use RouteFunctionDSL to map incoming request to HandlerFuncation:

    fun get(req: ServerRequest): Mono {
        return this.posts.findById(req.pathVariable("id"))
                .flatMap { post -> ok().body(Mono.just(post), Post::class.java) }
                .switchIfEmpty(notFound().build())
    }
    

    It is can be an expression, like:

    fun get(req: ServerRequest): Mono = this.posts.findById(req.pathVariable("id"))
                .flatMap { post -> ok().body(Mono.just(post), Post::class.java) }
                .switchIfEmpty(notFound().build())
    

    Check the complete example codes of Kotlin DSL here.

    If you prefer traditional controllers to expose REST APIs, try this approach.

    Firstly define an exception, eg. PostNotFoundException. Then throw it in controller.

     @GetMapping(value = "/{id}")
        public Mono get(@PathVariable(value = "id") Long id) {
            return this.posts.findById(id).switchIfEmpty(Mono.error(new PostNotFoundException(id)));
        }
    

    Define an ExceptionHandler to handle the exception, and register it in 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);
        };
    }
    

    Check the complete codes here. For Spring Boot users, check this sample.

    Update:In the latest spring 5.2, I found the general @RestControllerAdvice works for controllers in webflux applications.

提交回复
热议问题