@Override protected RouterFunction<?> routerFunction() { NestedHandler nestedHandler = new NestedHandler(); return nest(path("/foo/"), route(GET("/bar"), nestedHandler::pattern) .andRoute(GET("/baz"), nestedHandler::pattern)) .andNest(GET("/{foo}"), route(GET("/bar"), nestedHandler::variables).and( nest(GET("/{bar}"), route(GET("/{baz}"), nestedHandler::variables)))) .andRoute(path("/{qux}/quux").and(method(HttpMethod.GET)), nestedHandler::variables) .andRoute(all(), nestedHandler::variables); }
@Test public void andRoute() { RouterFunction<ServerResponse> routerFunction1 = request -> Mono.empty(); RequestPredicate requestPredicate = request -> true; RouterFunction<ServerResponse> result = routerFunction1.andRoute(requestPredicate, this::handlerMethod); assertNotNull(result); MockServerRequest request = MockServerRequest.builder().build(); Mono<? extends HandlerFunction<?>> resultHandlerFunction = result.route(request); StepVerifier.create(resultHandlerFunction) .expectNextCount(1) .expectComplete() .verify(); }
@Override protected RouterFunction<ServerResponse> routerFunction() { MultipartHandler multipartHandler = new MultipartHandler(); return route(POST("/multipartData"), multipartHandler::multipartData) .andRoute(POST("/parts"), multipartHandler::parts); }
static RouterFunction<?> doRoute(final ApiHandler apiHandler, final ErrorHandler errorHandler) { return nest(path(API_PATH), nest(accept(APPLICATION_JSON), route(GET(LOCATION_WITH_ADDRESS_PATH), apiHandler::getLocation) .andRoute(POST(LOCATION_PATH), apiHandler::postLocation) ).andOther(route(RequestPredicates.all(), errorHandler::notFound)) ); } }
/** * 注册自定义RouterFunction * RoouterFunction 类似 Spring Web MVC 的 @RequestMapping * 用来定义路由信息,每个路由会映射到一个处理方法,当接受 HTTP 请求时候会调用该处理方法。 */ @Bean public RouterFunction<ServerResponse> restaurantRouter() { RouterFunction<ServerResponse> router = route(GET("/reactive/restaurants").and(accept(APPLICATION_JSON_UTF8)), restaurantHandler::findAll) .andRoute(GET("/reactive/delay/restaurants").and(accept(APPLICATION_JSON_UTF8)), restaurantHandler::findAllDelay) .andRoute(GET("/reactive/restaurants/{id}").and(accept(APPLICATION_JSON_UTF8)), restaurantHandler::get) .andRoute(POST("/reactive/restaurants").and(accept(APPLICATION_JSON_UTF8)).and(contentType(APPLICATION_JSON_UTF8)), restaurantHandler::create) .andRoute(DELETE("/reactive/restaurants/{id}").and(accept(APPLICATION_JSON_UTF8)), restaurantHandler::delete) // 注册自定义HandlerFilterFunction .filter((request, next) -> { if (HttpMethod.PUT.equals(request.method())) { return ServerResponse.status(HttpStatus.BAD_REQUEST).build(); } return next.handle(request); }); return router; }
/** * Return a composed routing function that routes to the given router function if this * route does not match and the given request predicate applies. This method is a convenient * combination of {@link #and(RouterFunction)} and * {@link RouterFunctions#nest(RequestPredicate, RouterFunction)}. * @param predicate the predicate to test if this route does not match * @param routerFunction the router function to route to if this route does not match and * the predicate applies * @return a composed function that route to {@code routerFunction} if this route does not * match and if {@code predicate} applies */ default RouterFunction<T> andNest(RequestPredicate predicate, RouterFunction<T> routerFunction) { return and(RouterFunctions.nest(predicate, routerFunction)); }
@Test public void and() { HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().build(); RouterFunction<ServerResponse> routerFunction1 = request -> Mono.empty(); RouterFunction<ServerResponse> routerFunction2 = request -> Mono.just(handlerFunction); RouterFunction<ServerResponse> result = routerFunction1.and(routerFunction2); assertNotNull(result); MockServerRequest request = MockServerRequest.builder().build(); Mono<HandlerFunction<ServerResponse>> resultHandlerFunction = result.route(request); StepVerifier.create(resultHandlerFunction) .expectNext(handlerFunction) .expectComplete() .verify(); }
@Override protected RouterFunction<?> routerFunction() { RenderingResponseHandler handler = new RenderingResponseHandler(); RouterFunction<RenderingResponse> normalRoute = route(GET("/normal"), handler::render); RouterFunction<RenderingResponse> filteredRoute = route(GET("/filter"), handler::render) .filter(ofResponseProcessor( response -> RenderingResponse.from(response) .modelAttribute("qux", "quux") .build())); return normalRoute.and(filteredRoute); }
@Test public void andOther() { HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().body(fromObject("42")); RouterFunction<?> routerFunction1 = request -> Mono.empty(); RouterFunction<ServerResponse> routerFunction2 = request -> Mono.just(handlerFunction); RouterFunction<?> result = routerFunction1.andOther(routerFunction2); assertNotNull(result); MockServerRequest request = MockServerRequest.builder().build(); Mono<? extends HandlerFunction<?>> resultHandlerFunction = result.route(request); StepVerifier.create(resultHandlerFunction) .expectNextMatches(o -> o.equals(handlerFunction)) .expectComplete() .verify(); }
@Bean RouterFunction routes(final HandlerFunction<ServerResponse> fallbackHandler) { return nest( path("/"), nest( accept(APPLICATION_JSON), route( GET("/api/orders"), getOrdersHandler() ) ).andNest( accept(APPLICATION_JSON), route( GET("/api"), getCountQueryHandler() ) ) ).andOther( route( GET("/**"), fallbackHandler ) ) ; } }
public static RouterFunction<?> doRoute(final ApiHandler handler, final ErrorHandler errorHandler) { return ApiRouter .doRoute(handler, errorHandler) .andOther(StaticRouter.doRoute()); } }
@Override protected RouterFunction<?> routerFunction() { return RouterFunctions.route(RequestPredicates.GET("/"), request -> ServerResponse.ok().syncBody("FOO")) .andRoute(RequestPredicates.all(), request -> ServerResponse.ok().syncBody("BAR")); }
/** * Return a composed routing function that routes to the given handler function if this * route does not match and the given request predicate applies. This method is a convenient * combination of {@link #and(RouterFunction)} and * {@link RouterFunctions#route(RequestPredicate, HandlerFunction)}. * @param predicate the predicate to test if this route does not match * @param handlerFunction the handler function to route to if this route does not match and * the predicate applies * @return a composed function that route to {@code handlerFunction} if this route does not * match and if {@code predicate} applies */ default RouterFunction<T> andRoute(RequestPredicate predicate, HandlerFunction<T> handlerFunction) { return and(RouterFunctions.route(predicate, handlerFunction)); }
@Bean public RouterFunction<ServerResponse> route(TestHandler testHandler) { return RouterFunctions .route(RequestPredicates.GET("/route") .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), testHandler::route) .andRoute(RequestPredicates.POST("/route2") .and(RequestPredicates.contentType(MediaType.APPLICATION_JSON)), testHandler::route2) .andRoute(RequestPredicates.HEAD("/route3"), request -> ServerResponse.ok().build()); }
@Before public void setUp() { RouterFunction<ServerResponse> route = RouterFunctions .route(RequestPredicates.GET("/"), (request) -> ServerResponse.status(HttpStatus.OK) .body(fromObject(new Person("Jane", "Doe")))) .andRoute(RequestPredicates.GET("/{foo}/{bar}"), (request) -> ServerResponse.status(HttpStatus.OK) .body(fromObject(new Person("Jane", "Doe")))) .andRoute(RequestPredicates.POST("/upload"), (request) -> request.body(BodyExtractors.toMultipartData()) .map((parts) -> ServerResponse.status(HttpStatus.OK) .build().block())) .andRoute(RequestPredicates.GET("/set-cookie"), (request) -> ServerResponse.ok() .cookie(ResponseCookie.from("name", "value") .domain("localhost").httpOnly(true).build()) .build()); this.webTestClient = WebTestClient.bindToRouterFunction(route).configureClient() .baseUrl("https://api.example.com") .filter(documentationConfiguration(this.restDocumentation)).build(); }
@Override public void accept(Visitor visitor) { this.routerFunction.accept(visitor); }