黑马程序员技术交流社区
标题: 【上海校区网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.8... [打印本页]
作者: 不二晨 时间: 2018-7-19 09:22
标题: 【上海校区网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.8...
1. 概述本文主要分享 WebClientHttpRoutingFilter 的代码实现。
WebClientHttpRoutingFilter ,Http 路由网关过滤器。其根据 http:// 或 https:// 前缀( Scheme )过滤处理,使用基于 org.springframework.cloud.gateway.filter.WebClient 实现的 HttpClient 请求后端 Http 服务。
WebClientWriteResponseFilter ,与 WebClientHttpRoutingFilter 成对使用的网关过滤器。其将 WebClientWriteResponseFilter 请求后端 Http 服务的响应写回客户端。
大体流程如下 :
推荐 Spring Cloud 书籍:
推荐 Spring Cloud 视频:
2. 环境配置目前 WebClientHttpRoutingFilter / WebClientWriteResponseFilter 处于实验阶段,建议等正式发布在使用。
OK,下面我们来看看怎么配置环境。
第一步,在 NettyConfiguration 注释掉 #routingFilter(...) 和 #nettyWriteResponseFilter()两个 Bean 方法。
第二步,在 GatewayAutoConfiguration 打开 #webClientHttpRoutingFilter() 和#webClientWriteResponseFilter() 两个 Bean 方法。
第三步,配置完成,启动 Spring Cloud Gateway 。
3. WebClientHttpRoutingFilterorg.springframework.cloud.gateway.filter.WebClientHttpRoutingFilter ,Http 路由网关过滤器。
构造方法,代码如下 :
public class WebClientHttpRoutingFilter implements GlobalFilter, Ordered { private final WebClient webClient; public WebClientHttpRoutingFilter(WebClient webClient) { this.webClient = webClient; }}- webClient 属性,默认情况下,使用org.springframework.web.reactive.function.client.DefaultWebClient 实现类。通过该属性,请求后端的 Http 服务。
#getOrder() 方法,代码如下 :
@Overridepublic int getOrder() { return Ordered.LOWEST_PRECEDENCE;}
#filter(ServerWebExchange, GatewayFilterChain) 方法,代码如下 :
1: @Override 2: public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { 3: // 获得 requestUrl 4: URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR); 5: 6: // 判断是否能够处理 7: String scheme = requestUrl.getScheme(); 8: if (isAlreadyRouted(exchange) || (!scheme.equals("http") && !scheme.equals("https"))) { 9: return chain.filter(exchange);10: }11: 12: // 设置已经路由13: setAlreadyRouted(exchange);14: 15: ServerHttpRequest request = exchange.getRequest();16: 17: //TODO: support forms18: // Request Method19: HttpMethod method = request.getMethod();20: 21: // Request22: RequestBodySpec bodySpec = this.webClient.method(method)23: .uri(requestUrl)24: .headers(httpHeaders -> {25: httpHeaders.addAll(request.getHeaders());26: httpHeaders.remove(HttpHeaders.HOST);27: });28: 29: // Request Body30: RequestHeadersSpec<?> headersSpec;31: if (requiresBody(method)) {32: headersSpec = bodySpec.body(BodyInserters.fromDataBuffers(request.getBody()));33: } else {34: headersSpec = bodySpec;35: }36: 37: return headersSpec.exchange()38: // .log("webClient route")39: .flatMap(res -> {40: ServerHttpResponse response = exchange.getResponse();41: 42: // Response Header43: response.getHeaders().putAll(res.headers().asHttpHeaders());44: 45: // Response Status46: response.setStatusCode(res.statusCode());47: 48: // 设置 Response 到 CLIENT_RESPONSE_ATTR49: // Defer committing the response until all route filters have run50: // Put client response as ServerWebExchange attribute and write response later NettyWriteResponseFilter51: exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);52: return chain.filter(exchange);53: });54: }- 第 4 行 :获得 requestUrl 。
第 7 至 10 行 :判断 ForwardRoutingFilter 是否能够处理该请求,需要满足两个条件 :
第 13 行 :设置该请求已经被处理。代码如下 :
public static void setAlreadyRouted(ServerWebExchange exchange) { exchange.getAttributes().put(GATEWAY_ALREADY_ROUTED_ATTR, true);}第 17 行 :TODO 【3025】 目前暂不支持 forms 参数
- 第 22 至 35 行 :创建向后端服务的请求。
- 第 22 行 :设置 Method 属性。
- 第 24 至 27 行 :设置 Header 属性。
- 第 30 至 35 行 :设置 Body 属性。
- 第 37 行 :发起向后端服务的请求。
- 第 40 至 53 行 :处理返回自后端服务的相应。
- 第 43 行 :设置 response 的 Header 属性。
- 第 46 行 :设置 response 的 Status 属性。
- 第 51 行 :设置 res 到 CLIENT_RESPONSE_ATTR 。后续 WebClientWriteResponseFilter 将响应写回给客户端。
- 第 52 行 :提交过滤器链继续过滤。
4. WebClientWriteResponseFilterorg.springframework.cloud.gateway.filter.WebClientWriteResponseFilter ,Http 回写响应网关过滤器。
#getOrder() 方法,代码如下 :
public static final int WRITE_RESPONSE_FILTER_ORDER = -1; @Overridepublic int getOrder() { return WRITE_RESPONSE_FILTER_ORDER;}
#filter(ServerWebExchange, GatewayFilterChain) 方法,代码如下 :
1: @Override 2: public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { 3: // NOTICE: nothing in "pre" filter stage as CLIENT_RESPONSE_ATTR is not added 4: // until the WebHandler is run 5: return chain.filter(exchange).then(Mono.defer(() -> { 6: // 获得 Response 7: ClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR); 8: if (clientResponse == null) { 9: return Mono.empty();10: }11: log.trace("WebClientWriteResponseFilter start");12: ServerHttpResponse response = exchange.getResponse();13: 14: return response.writeWith(clientResponse.body(BodyExtractors.toDataBuffers())).log("webClient response");15: }));16: }- 第 5 行 :调用 #then(Mono) 方法,实现 After Filter 逻辑。
- 第 7 至 11 行 :从 CLIENT_RESPONSE_ATTR 中,获得 ClientResponse 。
- 第 14 行 :将 ClientResponse 写回给客户端。
5. 和 NettyRoutingFilter 对比
作者: 不二晨 时间: 2018-7-19 10:58
优秀,奈斯
作者: 摩西摩西OvO 时间: 2018-7-19 14:25

作者: 吴琼老师 时间: 2018-7-19 16:40

作者: 摩西摩西OvO 时间: 2018-7-23 13:35

作者: 摩西摩西OvO 时间: 2018-7-26 09:19
| 欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |