Spring Cloud Gateway(九):網關過濾器 GatewayFilter


本文基於 spring cloud gateway 2.0.1

1、簡介

GatewayFilter 網關過濾器用於攔截並鏈式處理web請求,可以實現橫切的與應用無關的需求,比如:安全、訪問超時的設置等。

GatewayFilter

從類圖中可以看到,GatewayFilter 有三個實現類:

  • OrderedGatewayFilter 是一個有序的網關過濾器

  • GatewayFilterAdapter 是一個適配器類,是web處理器(FilteringWebHandler)中的內部類

  • ModifyResponseGatewayFilter 是一個內部類,用於修改響應體

本文就分別介紹一下網關過濾器的實現類。

2、有序的網關過濾器 OrderedGatewayFilter

過濾器大多都是有優先級的,因此有序的網關過濾器的使用場景會很多。在實現過濾器接口的同時,有序網關過濾器也實現了 Ordered 接口,構造函數中傳入需要代理的網關過濾器以及優先級就可以構造一個有序的網關過濾器。具體的過濾功能的實現在被代理的過濾器中實現的,因此在此只需要調用代理的過濾器即可。

public class OrderedGatewayFilter implements GatewayFilter, Ordered {

	private final GatewayFilter delegate;
	private final int order;

	public OrderedGatewayFilter(GatewayFilter delegate, int order) {
		this.delegate = delegate;
		this.order = order;
	}
	--------------------------------省略-------------------------------
}

3、網關過濾器適配器 GatewayFilterAdapter

在網關過濾器鏈 GatewayFilterChain 中會使用 GatewayFilter 過濾請求,GatewayFilterAdapter的作用就是將全局過濾器 GlobalFilter 適配成 網關過濾器 GatewayFilter。

// FilteringWebHandler.java

private static class GatewayFilterAdapter implements GatewayFilter {

		private final GlobalFilter delegate;

		public GatewayFilterAdapter(GlobalFilter delegate) {
			this.delegate = delegate;
		}

		@Override
		public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
			return this.delegate.filter(exchange, chain);
		}

		@Override
		public String toString() {
			final StringBuilder sb = new StringBuilder("GatewayFilterAdapter{");
			sb.append("delegate=").append(delegate);
			sb.append('}');
			return sb.toString();
		}
	}

4、ModifyResponseGatewayFilter

ModifyResponseGatewayFilter 是 ModifyResponseBodyGatewayFilterFactory 的內部類,用於修改響應體的信息

// ModifyResponseBodyGatewayFilterFactory.java

	public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered {
		private final Config config;

		public ModifyResponseGatewayFilter(Config config) {
			this.config = config;
		}

		@Override
		@SuppressWarnings("unchecked")
		public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

			ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {

				@Override
				public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {

					Class inClass = config.getInClass();
					Class outClass = config.getOutClass();

					String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
					HttpHeaders httpHeaders = new HttpHeaders();
					//explicitly add it in this way instead of 'httpHeaders.setContentType(originalResponseContentType)'
					//this will prevent exception in case of using non-standard media types like "Content-Type: image"
					httpHeaders.add(HttpHeaders.CONTENT_TYPE, originalResponseContentType);
					ResponseAdapter responseAdapter = new ResponseAdapter(body, httpHeaders);
					DefaultClientResponse clientResponse = new DefaultClientResponse(responseAdapter, ExchangeStrategies.withDefaults());

					//TODO: flux or mono
					Mono modifiedBody = clientResponse.bodyToMono(inClass)
							.flatMap(originalBody -> config.rewriteFunction.apply(exchange, originalBody));

					BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass);
					CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, exchange.getResponse().getHeaders());
					return bodyInserter.insert(outputMessage, new BodyInserterContext())
							.then(Mono.defer(() -> {
								long contentLength1 = getDelegate().getHeaders().getContentLength();
								Flux<DataBuffer> messageBody = outputMessage.getBody();
								//TODO: if (inputStream instanceof Mono) {
									HttpHeaders headers = getDelegate().getHeaders();
									if (/*headers.getContentLength() < 0 &&*/ !headers.containsKey(HttpHeaders.TRANSFER_ENCODING)) {
										messageBody = messageBody.doOnNext(data -> headers.setContentLength(data.readableByteCount()));
									}
								// }
								//TODO: use isStreamingMediaType?
								return getDelegate().writeWith(messageBody);
							}));
				}

				@Override
				public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
					return writeWith(Flux.from(body)
							.flatMapSequential(p -> p));
				}
			};

			return chain.filter(exchange.mutate().response(responseDecorator).build());
		}

		@Override
		public int getOrder() {
			return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
		}

	}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM