WebFlux请求处理过程

WebFlux请求处理过程

  • 1. 请求处理路径
  • 2. WebFlux请求处理过程
  • 3. 三种HandlerAdaptor
    • 3.1 RequestMapping方式定义URI
    • 3.2 HandlerFunction方式定义URI
    • 3.3 Spring Cloud Gateway对WebFlux的应用
      • 3.3.1 org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter
      • 3.3.2 Spring Cloud Gateway HandlerMapping

1. 请求处理路径

Rector Request -> Reactor-HttpHandler-Adapter -> Http-WebHandler-Adapter -> ExceptionHandling-WebHandler -> Filtering-WebHandler -> WebFilter -> DispatcherHandler -> HandlerMapping (get handler match the request) -> HandlerAdapter -> HandlerResultAdaptor

2. WebFlux请求处理过程

org.springframework.web.reactive.DispatcherHandler#initStrategies

protected void initStrategies(ApplicationContext context) {
	Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
			context, HandlerMapping.class, true, false);

	ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
	AnnotationAwareOrderComparator.sort(mappings);
	this.handlerMappings = Collections.unmodifiableList(mappings);

	Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
			context, HandlerAdapter.class, true, false);

	this.handlerAdapters = new ArrayList<>(adapterBeans.values());
	AnnotationAwareOrderComparator.sort(this.handlerAdapters);

	Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
			context, HandlerResultHandler.class, true, false);

	this.resultHandlers = new ArrayList<>(beans.values());
	AnnotationAwareOrderComparator.sort(this.resultHandlers);
}

org.springframework.web.reactive.DispatcherHandler#handle

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
	if (this.handlerMappings == null) {
		return createNotFoundError();
	}
	return Flux.fromIterable(this.handlerMappings)
			.concatMap(mapping -> mapping.getHandler(exchange))
			.next()
			.switchIfEmpty(createNotFoundError())
			.flatMap(handler -> invokeHandler(exchange, handler))
			.flatMap(result -> handleResult(exchange, result));
}

3. 三种HandlerAdaptor

RequestMappingHandlerAdapter
HandlerFunctionAdapter
SimpleHandlerAdapter -> spring cloud gateway goes this.

3.1 RequestMapping方式定义URI

我要领养一只萌宠!

@RequestMapping("/game/animal")
@RestController
public class AnimalController {
    private final List<String> ANIMALS = Arrays.asList("Monkey", "Tiger", "Elephant", "kangaroo", "Rabbit", "Goat", "Mouse", "Cat", "Dog", "Chicken", "Ant", "Bear");

    @RequestMapping("/get")
    public Mono<String> getAnimal(ServerHttpRequest request) {
        List<String> fromList = request.getHeaders().get("from");

        if (CollectionUtils.isEmpty(fromList)) {
            return Mono.just("From is required in header!");
        }

        StringBuilder sb = new StringBuilder()
                .append("Request from ")
                .append(CollectionUtils.isEmpty(fromList) ? "Universal" : fromList.get(0))
                .append("! ").append("Congratulations! You got a pet ")
                .append(ANIMALS.get(new Random().nextInt(ANIMALS.size() - 1)))
                .append("!");

        return Mono.just(sb.toString());
    }
}

3.2 HandlerFunction方式定义URI

永恒的经典,say hello to the world!

@Configuration
public class DemoRoutesConfiguration {
    @Bean
    public RouterFunction<ServerResponse> demoRoutes() {
        return RouterFunctions.route(
                GET("/helloWorld").and(accept(MediaType.APPLICATION_JSON)),
                request -> ServerResponse.ok().syncBody("Hello World!")
        );
    }
}

3.3 Spring Cloud Gateway对WebFlux的应用

3.3.1 org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter

3.3.2 Spring Cloud Gateway HandlerMapping

所有的gateway请求最终通过org.springframework.cloud.gateway.handler.FilteringWebHandler进行处理。

  1. 接收请求
  2. 调用lookupRoute方法,遍历所有的路由,通过Predicate校验并匹配路由,取满足条件的第一个路由
  3. 将路由设置到ServerWebExchange对象,返回FilteringWebHandler
  4. FilteringWebHandler组合GlobalFilter和Route内注册GatewayFilter,按Comparator进行排序
  5. 创建DefaultGatewayFilterChain并执行filter

org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping#getHandlerInternal

@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
	// don't handle requests on management port if set and different than server port
	if (this.managementPortType == DIFFERENT && this.managementPort != null
			&& exchange.getRequest().getURI().getPort() == this.managementPort) {
		return Mono.empty();
	}
	exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());

	return lookupRoute(exchange)
			// .log("route-predicate-handler-mapping", Level.FINER) //name this
			.flatMap((Function<Route, Mono<?>>) r -> {
				exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
				if (logger.isDebugEnabled()) {
					logger.debug(
							"Mapping [" + getExchangeDesc(exchange) + "] to " + r);
				}

				exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
				return Mono.just(webHandler);
			}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
				exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
				if (logger.isTraceEnabled()) {
					logger.trace("No RouteDefinition found for ["
							+ getExchangeDesc(exchange) + "]");
				}
			})));
}
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
	return this.routeLocator.getRoutes()
			// individually filter routes so that filterWhen error delaying is not a
			// problem
			.concatMap(route -> Mono.just(route).filterWhen(r -> {
				// add the current route we are testing
				exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
				return r.getPredicate().apply(exchange);
			})
					// instead of immediately stopping main flux due to error, log and
					// swallow it
					.doOnError(e -> logger.error(
							"Error applying predicate for route: " + route.getId(),
							e))
					.onErrorResume(e -> Mono.empty()))
			// .defaultIfEmpty() put a static Route not found
			// or .switchIfEmpty()
			// .switchIfEmpty(Mono.empty().log("noroute"))
			.next()
			// TODO: error handling
			.map(route -> {
				if (logger.isDebugEnabled()) {
					logger.debug("Route matched: " + route.getId());
				}
				validateRoute(route, exchange);
				return route;
			});

	/*
	 * TODO: trace logging if (logger.isTraceEnabled()) {
	 * logger.trace("RouteDefinition did not match: " + routeDefinition.getId()); }
	 */
}

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
	Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
	List<GatewayFilter> gatewayFilters = route.getFilters();

	List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
	combined.addAll(gatewayFilters);
	// TODO: needed or cached?
	AnnotationAwareOrderComparator.sort(combined);

	if (logger.isDebugEnabled()) {
		logger.debug("Sorted gatewayFilterFactories: " + combined);
	}

	return new DefaultGatewayFilterChain(combined).filter(exchange);
}

你可能感兴趣的:(Spring,WebFlux)