Add TomcatConnectorCustomizer

... and ServerProperties.Tomcat.maxThreads to conveniently
limit the thread pool size in the Connector.
pull/64/head
Dave Syer 11 years ago
parent c7dc95692c
commit c661a74c75

@ -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();

Loading…
Cancel
Save