Register @WebListeners in a way that allows them to register components
Previously, @WebListeners were discovered via custom component scanning and then registered programmatically via the ServletContext. The servlet spec requires any ServletContextListener registered in this manner to be prohibited from programatically configuring servlets, filters, and listeners. This left us not strictly complying with the servlet spec as a ServletContextListener registered via a @WebListener annotation should be able to programatically configure other components. This commit updates WebListenerHandler to register each @WebListener component directly with Jetty, Tomcat, or Undertow rather than via the ServletContext API. This ensure that any @WebListener-annoated ServletContextListener registered via servlet component scanning is able to programatically register servlets, filters, and listeners. There is a small chance that this will be a breaking change for some users: 1. The ServletListenerRegistrationBeans that were previously defined for each @WebListener will now be WebListenerHandler.WebListenerRegistrars 2. Each @WebListener-annotated class will now be instantiated by Jetty, Tomcat, or Undertow. Jetty and Tomcat both require the class to be public and have a public default constructor. Previously, a package-private class or default constructor could be used as the instantiation was performed by Spring Framework. Undertow is not affected as it can instantiate a package-private type. Fixes gh-18303
This commit is contained in:
committed by
Phillip Webb
parent
1a3f810cd8
commit
fafc0a91e3
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.autoconfigure.web.servlet;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletRequest;
|
||||
@@ -24,6 +25,7 @@ import javax.servlet.ServletRequest;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -38,6 +40,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.WebListenerRegistrar;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@@ -69,8 +72,10 @@ import org.springframework.web.filter.ForwardedHeaderFilter;
|
||||
public class ServletWebServerFactoryAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
|
||||
return new ServletWebServerFactoryCustomizer(serverProperties);
|
||||
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties,
|
||||
ObjectProvider<WebListenerRegistrar> webListenerRegistrars) {
|
||||
return new ServletWebServerFactoryCustomizer(serverProperties,
|
||||
webListenerRegistrars.orderedStream().collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -16,9 +16,13 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.web.servlet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.boot.web.servlet.WebListenerRegistrar;
|
||||
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
@@ -37,8 +41,16 @@ public class ServletWebServerFactoryCustomizer
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
|
||||
private final Iterable<WebListenerRegistrar> webListenerRegistrars;
|
||||
|
||||
public ServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
|
||||
this(serverProperties, Collections.emptyList());
|
||||
}
|
||||
|
||||
public ServletWebServerFactoryCustomizer(ServerProperties serverProperties,
|
||||
List<WebListenerRegistrar> webListenerRegistrars) {
|
||||
this.serverProperties = serverProperties;
|
||||
this.webListenerRegistrars = webListenerRegistrars;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,6 +74,9 @@ public class ServletWebServerFactoryCustomizer
|
||||
map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader);
|
||||
map.from(this.serverProperties.getServlet()::getContextParameters).to(factory::setInitParameters);
|
||||
map.from(this.serverProperties.getShutdown()).to(factory::setShutdown);
|
||||
for (WebListenerRegistrar registrar : this.webListenerRegistrars) {
|
||||
registrar.register(factory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user