diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index f8cb5dd03572..10a9ca09c44e 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -35,6 +35,7 @@ import jakarta.servlet.Filter; import jakarta.servlet.MultipartConfigElement; import jakarta.servlet.Servlet; +import jakarta.servlet.annotation.WebInitParam; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -63,6 +64,7 @@ * @author Phillip Webb * @author Brian Clozel * @author Moritz Halbritter + * @author Dmytro Danilenkov * @since 1.4.0 */ public class ServletContextInitializerBeans extends AbstractCollection { @@ -318,6 +320,13 @@ private void configureFromAnnotation(ServletRegistrationBean bean, Serv bean.setIgnoreRegistrationFailure(registration.ignoreRegistrationFailure()); bean.setLoadOnStartup(registration.loadOnStartup()); bean.setUrlMappings(Arrays.asList(registration.urlMappings())); + + for (WebInitParam param : registration.initParameters()) { + bean.addInitParameter(param.name(), param.value()); + } + + bean.setMultipartConfig(new MultipartConfigElement(registration.multipartConfig())); + } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java index e515747295fa..e054a8b9e367 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java @@ -23,6 +23,8 @@ import java.lang.annotation.Target; import jakarta.servlet.Servlet; +import jakarta.servlet.annotation.MultipartConfig; +import jakarta.servlet.annotation.WebInitParam; import org.springframework.core.Ordered; import org.springframework.core.annotation.AliasFor; @@ -33,6 +35,7 @@ * annotation-based alternative to {@link ServletRegistrationBean}. * * @author Moritz Halbritter + * @author Dmytro Danilenkov * @since 3.5.0 * @see ServletRegistrationBean */ @@ -87,4 +90,16 @@ */ int loadOnStartup() default -1; + /** + * Init parameters to set on the servlet (mirrors {@code @WebInitParam} usage). + * @return array of {@link WebInitParam} + */ + WebInitParam[] initParameters() default {}; + + /** + * Multipart configuration. + * @return multipart config {@link MultipartConfig} + */ + MultipartConfig multipartConfig() default @MultipartConfig; + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java index 0d6b2389e6ea..6c5d96f5ef9e 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java @@ -25,6 +25,8 @@ import jakarta.servlet.ServletContext; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; +import jakarta.servlet.annotation.MultipartConfig; +import jakarta.servlet.annotation.WebInitParam; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -47,6 +49,7 @@ * * @author Andy Wilkinson * @author Moritz Halbritter + * @author Dmytro Danilenkov */ class ServletContextInitializerBeansTests { @@ -195,6 +198,29 @@ void shouldApplyOrderFromOrderAttribute() { .isEqualTo(ServletConfigurationWithAnnotationAndOrder.ORDER)); } + @Test + void shouldApplyExtendedServletRegistrationAnnotation() { + load(ServletConfigurationWithExtendedAttributes.class); + ServletContextInitializerBeans initializerBeans = new ServletContextInitializerBeans( + this.context.getBeanFactory(), TestServletContextInitializer.class); + assertThatSingleServletRegistration(initializerBeans, (bean) -> { + assertThat(bean.getServletName()).isEqualTo("extended"); + assertThat(bean.getUrlMappings()).containsExactly("/extended/*"); + assertThat(bean.getInitParameters()).containsEntry("hello", "world").containsEntry("flag", "true"); + assertThat(bean.getMultipartConfig()).isNotNull(); + assertThat(bean.getMultipartConfig().getLocation()).isEqualTo("/tmp"); + assertThat(bean.getMultipartConfig().getMaxFileSize()).isEqualTo(1024); + assertThat(bean.getMultipartConfig().getMaxRequestSize()).isEqualTo(4096); + assertThat(bean.getMultipartConfig().getFileSizeThreshold()).isEqualTo(128); + }); + + } + + private void assertThatSingleServletRegistration(ServletContextInitializerBeans initializerBeans, + ThrowingConsumer> code) { + assertThatSingleRegistration(initializerBeans, ServletRegistrationBean.class, code::acceptThrows); + } + private void load(Class... configuration) { this.context = new AnnotationConfigApplicationContext(configuration); } @@ -421,4 +447,19 @@ public void onStartup(ServletContext servletContext) { } + @Configuration(proxyBeanMethods = false) + static class ServletConfigurationWithExtendedAttributes { + + @Bean + @ServletRegistration(name = "extended", urlMappings = "/extended/*", + initParameters = { @WebInitParam(name = "hello", value = "world"), + @WebInitParam(name = "flag", value = "true") }, + multipartConfig = @MultipartConfig(location = "/tmp", maxFileSize = 1024, maxRequestSize = 4096, + fileSizeThreshold = 128)) + TestServlet testServletWithInitParametersAndMultipart() { + return new TestServlet(); + } + + } + }