Refactor FilterWebHandler and DefaultWebFilterChain
The chain is initialized once and re-used vs creating the "next" chains on every request.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,11 +19,12 @@ package org.springframework.web.server.handler;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
@@ -32,34 +33,80 @@ import org.springframework.web.server.WebHandler;
|
||||
/**
|
||||
* Default implementation of {@link WebFilterChain}.
|
||||
*
|
||||
* <p>Each instance of this class represents one link in the chain. The public
|
||||
* constructor {@link #DefaultWebFilterChain(WebHandler, List)}
|
||||
* initializes the full chain and represents its first link.
|
||||
*
|
||||
* <p>This class is immutable and thread-safe. It can be created once and
|
||||
* re-used to handle request concurrently.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class DefaultWebFilterChain implements WebFilterChain {
|
||||
|
||||
private final List<WebFilter> filters;
|
||||
private final List<WebFilter> allFilters;
|
||||
|
||||
private final WebHandler handler;
|
||||
|
||||
private final int index;
|
||||
@Nullable
|
||||
private final WebFilter currentFilter;
|
||||
|
||||
@Nullable
|
||||
private final DefaultWebFilterChain next;
|
||||
|
||||
|
||||
public DefaultWebFilterChain(WebHandler handler, WebFilter... filters) {
|
||||
/**
|
||||
* Public constructor with the list of filters and the target handler to use.
|
||||
* @param handler the target handler
|
||||
* @param filters the filters ahead of the handler
|
||||
* @since 5.1
|
||||
*/
|
||||
public DefaultWebFilterChain(WebHandler handler, List<WebFilter> filters) {
|
||||
Assert.notNull(handler, "WebHandler is required");
|
||||
this.filters = ObjectUtils.isEmpty(filters) ? Collections.emptyList() : Arrays.asList(filters);
|
||||
this.allFilters = Collections.unmodifiableList(filters);
|
||||
this.handler = handler;
|
||||
this.index = 0;
|
||||
DefaultWebFilterChain chain = initChain(filters, handler);
|
||||
this.currentFilter = chain.currentFilter;
|
||||
this.next = chain.next;
|
||||
}
|
||||
|
||||
private DefaultWebFilterChain(DefaultWebFilterChain parent, int index) {
|
||||
this.filters = parent.getFilters();
|
||||
this.handler = parent.getHandler();
|
||||
this.index = index;
|
||||
private static DefaultWebFilterChain initChain(List<WebFilter> filters, WebHandler handler) {
|
||||
DefaultWebFilterChain chain = new DefaultWebFilterChain(filters, handler, null, null);
|
||||
ListIterator<? extends WebFilter> iterator = filters.listIterator(filters.size());
|
||||
while (iterator.hasPrevious()) {
|
||||
chain = new DefaultWebFilterChain(filters, handler, iterator.previous(), chain);
|
||||
}
|
||||
return chain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to represent one link in the chain.
|
||||
*/
|
||||
private DefaultWebFilterChain(List<WebFilter> allFilters, WebHandler handler,
|
||||
@Nullable WebFilter currentFilter, @Nullable DefaultWebFilterChain next) {
|
||||
|
||||
this.allFilters = allFilters;
|
||||
this.currentFilter = currentFilter;
|
||||
this.handler = handler;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor with the list of filters and the target handler to use.
|
||||
* @param handler the target handler
|
||||
* @param filters the filters ahead of the handler
|
||||
* @deprecated as of 5.1 this constructor is deprecated in favor of
|
||||
* {@link #DefaultWebFilterChain(WebHandler, List)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public DefaultWebFilterChain(WebHandler handler, WebFilter... filters) {
|
||||
this(handler, Arrays.asList(filters));
|
||||
}
|
||||
|
||||
|
||||
public List<WebFilter> getFilters() {
|
||||
return this.filters;
|
||||
return this.allFilters;
|
||||
}
|
||||
|
||||
public WebHandler getHandler() {
|
||||
@@ -69,16 +116,10 @@ public class DefaultWebFilterChain implements WebFilterChain {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange) {
|
||||
return Mono.defer(() -> {
|
||||
if (this.index < this.filters.size()) {
|
||||
WebFilter filter = this.filters.get(this.index);
|
||||
WebFilterChain chain = new DefaultWebFilterChain(this, this.index + 1);
|
||||
return filter.filter(exchange, chain);
|
||||
}
|
||||
else {
|
||||
return this.handler.handle(exchange);
|
||||
}
|
||||
});
|
||||
return Mono.defer(() ->
|
||||
this.currentFilter != null && this.next != null ?
|
||||
this.currentFilter.filter(exchange, this.next) :
|
||||
this.handler.handle(exchange));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.web.server.handler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -34,16 +33,16 @@ import org.springframework.web.server.WebHandler;
|
||||
*/
|
||||
public class FilteringWebHandler extends WebHandlerDecorator {
|
||||
|
||||
private final WebFilter[] filters;
|
||||
private final DefaultWebFilterChain chain;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param filters the chain of filters
|
||||
*/
|
||||
public FilteringWebHandler(WebHandler webHandler, List<WebFilter> filters) {
|
||||
super(webHandler);
|
||||
this.filters = filters.toArray(new WebFilter[0]);
|
||||
public FilteringWebHandler(WebHandler handler, List<WebFilter> filters) {
|
||||
super(handler);
|
||||
this.chain = new DefaultWebFilterChain(handler, filters);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,15 +50,13 @@ public class FilteringWebHandler extends WebHandlerDecorator {
|
||||
* Return a read-only list of the configured filters.
|
||||
*/
|
||||
public List<WebFilter> getFilters() {
|
||||
return Arrays.asList(this.filters);
|
||||
return this.chain.getFilters();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange) {
|
||||
return this.filters.length != 0 ?
|
||||
new DefaultWebFilterChain(getDelegate(), this.filters).filter(exchange) :
|
||||
super.handle(exchange);
|
||||
return this.chain.filter(exchange);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user