Add TomcatConnectorCustomizer
... and ServerProperties.Tomcat.maxThreads to conveniently limit the thread pool size in the Connector.
This commit is contained in:
@@ -22,12 +22,16 @@ import java.net.InetAddress;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.valves.AccessLogValve;
|
||||
import org.apache.catalina.valves.RemoteIpValve;
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.ProtocolHandler;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@@ -119,6 +123,16 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||
|
||||
private int backgroundProcessorDelay = 30; // seconds
|
||||
|
||||
private int maxThreads = 0; // Number of threads in protocol handler
|
||||
|
||||
public int getMaxThreads() {
|
||||
return this.maxThreads;
|
||||
}
|
||||
|
||||
public void setMaxThreads(int maxThreads) {
|
||||
this.maxThreads = maxThreads;
|
||||
}
|
||||
|
||||
public boolean getAccessLogEnabled() {
|
||||
return this.accessLogEnabled;
|
||||
}
|
||||
@@ -189,6 +203,19 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||
factory.addContextValves(valve);
|
||||
}
|
||||
|
||||
if (this.maxThreads > 0) {
|
||||
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
|
||||
@Override
|
||||
public void customize(Connector connector) {
|
||||
ProtocolHandler handler = connector.getProtocolHandler();
|
||||
if (handler instanceof AbstractProtocol) {
|
||||
AbstractProtocol protocol = (AbstractProtocol) handler;
|
||||
protocol.setMaxThreads(Tomcat.this.maxThreads);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (this.accessLogEnabled) {
|
||||
AccessLogValve valve = new AccessLogValve();
|
||||
String accessLogPattern = getAccessLogPattern();
|
||||
@@ -202,7 +229,6 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||
factory.addContextValves(valve);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.context.embedded.tomcat;
|
||||
|
||||
import org.apache.catalina.connector.Connector;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface TomcatConnectorCustomizer {
|
||||
|
||||
/**
|
||||
* @param connector the connector to customize
|
||||
*/
|
||||
void customize(Connector connector);
|
||||
|
||||
}
|
||||
@@ -84,6 +84,8 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||
|
||||
private List<TomcatContextCustomizer> tomcatContextCustomizers = new ArrayList<TomcatContextCustomizer>();
|
||||
|
||||
private List<TomcatConnectorCustomizer> tomcatConnectorCustomizers = new ArrayList<TomcatConnectorCustomizer>();
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
private String protocol = DEFAULT_PROTOCOL;
|
||||
@@ -203,6 +205,9 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||
// If ApplicationContext is slow to start we want Tomcat not to bind to the socket
|
||||
// prematurely...
|
||||
connector.setProperty("bindOnInit", "false");
|
||||
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
|
||||
customizer.customize(connector);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,6 +389,40 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||
this.tomcatContextCustomizers.addAll(Arrays.asList(tomcatContextCustomizers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@link TomcatConnectorCustomizer}s that should be applied to the Tomcat
|
||||
* {@link Connector} . Calling this method will replace any existing customizers.
|
||||
* @param tomcatConnectorCustomizers the customizers to set
|
||||
*/
|
||||
public void setTomcatConnectorCustomizers(
|
||||
Collection<? extends TomcatConnectorCustomizer> tomcatConnectorCustomizers) {
|
||||
Assert.notNull(this.contextLifecycleListeners,
|
||||
"TomcatConnectorCustomizer must not be null");
|
||||
this.tomcatConnectorCustomizers = new ArrayList<TomcatConnectorCustomizer>(
|
||||
tomcatConnectorCustomizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@link TomcatContextCustomizer}s that should be added to the Tomcat
|
||||
* {@link Connector}.
|
||||
* @param tomcatConnectorCustomizers the customizers to add
|
||||
*/
|
||||
public void addConnectorCustomizers(
|
||||
TomcatConnectorCustomizer... tomcatConnectorCustomizers) {
|
||||
Assert.notNull(this.tomcatContextCustomizers,
|
||||
"TomcatConnectorCustomizer must not be null");
|
||||
this.tomcatConnectorCustomizers.addAll(Arrays.asList(tomcatConnectorCustomizers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mutable collection of the {@link TomcatContextCustomizer}s that will be
|
||||
* applied to the Tomcat {@link Context} .
|
||||
* @return the tomcatContextCustomizers the listeners that will be applied
|
||||
*/
|
||||
public Collection<TomcatConnectorCustomizer> getTomcatConnectorCustomizers() {
|
||||
return this.tomcatConnectorCustomizers;
|
||||
}
|
||||
|
||||
private static class TomcatErrorPage {
|
||||
|
||||
private String location;
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.LifecycleEvent;
|
||||
import org.apache.catalina.LifecycleListener;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
@@ -80,6 +81,22 @@ public class TomcatEmbeddedServletContainerFactoryTests extends
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatConnectorCustomizers() throws Exception {
|
||||
TomcatEmbeddedServletContainerFactory factory = getFactory();
|
||||
TomcatConnectorCustomizer[] listeners = new TomcatConnectorCustomizer[4];
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i] = mock(TomcatConnectorCustomizer.class);
|
||||
}
|
||||
factory.setTomcatConnectorCustomizers(Arrays.asList(listeners[0], listeners[1]));
|
||||
factory.addConnectorCustomizers(listeners[2], listeners[3]);
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
InOrder ordered = inOrder((Object[]) listeners);
|
||||
for (TomcatConnectorCustomizer listener : listeners) {
|
||||
ordered.verify(listener).customize((Connector) anyObject());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionTimeout() throws Exception {
|
||||
TomcatEmbeddedServletContainerFactory factory = getFactory();
|
||||
|
||||
Reference in New Issue
Block a user