Enable APR optional support in Tomcat servers
This commits adds the AprLifecycleListener as a default LifecycleListener in order to detect and use automatically the tomcatnative library if it is available, for SSL support. This feature can be useful for both performance reasons or for supporting ALPN when using JDK8. See gh-10043 Closes gh-9964
This commit is contained in:
parent
5cf50b6ccc
commit
5f57578b71
|
|
@ -24,7 +24,9 @@ import java.util.List;
|
|||
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.Host;
|
||||
import org.apache.catalina.LifecycleListener;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.core.AprLifecycleListener;
|
||||
import org.apache.catalina.loader.WebappLoader;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
|
|
@ -53,6 +55,8 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
|||
|
||||
private String protocol = DEFAULT_PROTOCOL;
|
||||
|
||||
private List<LifecycleListener> contextLifecycleListeners = Arrays.asList(new AprLifecycleListener());
|
||||
|
||||
private List<TomcatContextCustomizer> tomcatContextCustomizers = new ArrayList<>();
|
||||
|
||||
private List<TomcatConnectorCustomizer> tomcatConnectorCustomizers = new ArrayList<>();
|
||||
|
|
@ -115,6 +119,9 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
|||
* @param context the Tomcat context
|
||||
*/
|
||||
protected void configureContext(Context context) {
|
||||
for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {
|
||||
context.addLifecycleListener(lifecycleListener);
|
||||
}
|
||||
for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {
|
||||
customizer.customize(context);
|
||||
}
|
||||
|
|
@ -211,6 +218,39 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
|||
return this.tomcatConnectorCustomizers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@link LifecycleListener}s that should be applied to the Tomcat {@link Context}
|
||||
* . Calling this method will replace any existing listeners.
|
||||
* @param contextLifecycleListeners the listeners to set
|
||||
*/
|
||||
public void setContextLifecycleListeners(
|
||||
Collection<? extends LifecycleListener> contextLifecycleListeners) {
|
||||
Assert.notNull(contextLifecycleListeners,
|
||||
"ContextLifecycleListeners must not be null");
|
||||
this.contextLifecycleListeners = new ArrayList<>(contextLifecycleListeners);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mutable collection of the {@link LifecycleListener}s that will be applied
|
||||
* to the Tomcat {@link Context} .
|
||||
* @return the context lifecycle listeners that will be applied
|
||||
*/
|
||||
public Collection<LifecycleListener> getContextLifecycleListeners() {
|
||||
return this.contextLifecycleListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@link LifecycleListener}s that should be added to the Tomcat {@link Context}.
|
||||
* @param contextLifecycleListeners the listeners to add
|
||||
*/
|
||||
public void addContextLifecycleListeners(
|
||||
LifecycleListener... contextLifecycleListeners) {
|
||||
Assert.notNull(contextLifecycleListeners,
|
||||
"ContextLifecycleListeners must not be null");
|
||||
this.contextLifecycleListeners.addAll(Arrays.asList(contextLifecycleListeners));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory method called to create the {@link TomcatWebServer}. Subclasses can
|
||||
* override this method to return a different {@link TomcatWebServer} or apply
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import org.apache.catalina.WebResourceRoot.ResourceSetType;
|
|||
import org.apache.catalina.WebResourceSet;
|
||||
import org.apache.catalina.Wrapper;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.core.AprLifecycleListener;
|
||||
import org.apache.catalina.loader.WebappLoader;
|
||||
import org.apache.catalina.session.StandardManager;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
|
|
@ -122,7 +123,7 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
|||
|
||||
private List<Valve> contextValves = new ArrayList<>();
|
||||
|
||||
private List<LifecycleListener> contextLifecycleListeners = new ArrayList<>();
|
||||
private List<LifecycleListener> contextLifecycleListeners = Arrays.asList(new AprLifecycleListener());
|
||||
|
||||
private List<TomcatContextCustomizer> tomcatContextCustomizers = new ArrayList<>();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,13 +19,17 @@ package org.springframework.boot.web.embedded.tomcat;
|
|||
import java.util.Arrays;
|
||||
|
||||
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.core.AprLifecycleListener;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
|
@ -60,6 +64,30 @@ public class TomcatReactiveWebServerFactoryTests
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultTomcatListeners() throws Exception {
|
||||
TomcatReactiveWebServerFactory factory = getFactory();
|
||||
assertThat(factory.getContextLifecycleListeners())
|
||||
.hasSize(1)
|
||||
.first().isInstanceOf(AprLifecycleListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatListeners() throws Exception {
|
||||
TomcatReactiveWebServerFactory factory = getFactory();
|
||||
LifecycleListener[] listeners = new LifecycleListener[4];
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i] = mock(LifecycleListener.class);
|
||||
}
|
||||
factory.setContextLifecycleListeners(Arrays.asList(listeners[0], listeners[1]));
|
||||
factory.addContextLifecycleListeners(listeners[2], listeners[3]);
|
||||
this.webServer = factory.getWebServer(mock(HttpHandler.class));
|
||||
InOrder ordered = inOrder((Object[]) listeners);
|
||||
for (LifecycleListener listener : listeners) {
|
||||
ordered.verify(listener).lifecycleEvent(any(LifecycleEvent.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNullConnectorCustomizersShouldThrowException() {
|
||||
TomcatReactiveWebServerFactory factory = getFactory();
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import org.apache.catalina.Service;
|
|||
import org.apache.catalina.SessionIdGenerator;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.core.AprLifecycleListener;
|
||||
import org.apache.catalina.core.StandardWrapper;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.catalina.util.CharsetMapper;
|
||||
|
|
@ -102,6 +103,14 @@ public class TomcatServletWebServerFactoryTests
|
|||
tomcatWebServer.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultTomcatListeners() throws Exception {
|
||||
TomcatServletWebServerFactory factory = getFactory();
|
||||
assertThat(factory.getContextLifecycleListeners())
|
||||
.hasSize(1)
|
||||
.first().isInstanceOf(AprLifecycleListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tomcatListeners() throws Exception {
|
||||
TomcatServletWebServerFactory factory = getFactory();
|
||||
|
|
|
|||
Loading…
Reference in New Issue