From 1ae91a135c1e58012fe6eefbdaf739597b3f4861 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 25 Apr 2014 14:41:36 +0100 Subject: [PATCH] Polish MultipartConfigElement support Polish MultipartConfigElement changes introduced in commit e8e59ea6 as follows: - Fix javadoc formatting - Fix tab/spaces formatting - Fix asciidoc formatting - Move creation of MultipartConfigElement into MultipartProperties - Add @Since tags - Restore random port in tests --- .../web/MultipartAutoConfiguration.java | 25 +--- .../web/MultipartProperties.java | 138 +++++++++++------- .../web/MultipartAutoConfigurationTests.java | 57 +++++--- spring-boot-docs/src/main/asciidoc/howto.adoc | 30 ++-- 4 files changed, 144 insertions(+), 106 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java index 369d79162c..ae9715a45f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java @@ -25,11 +25,9 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; -import org.springframework.boot.context.embedded.MultipartConfigFactory; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.util.StringUtils; import org.springframework.web.multipart.support.StandardServletMultipartResolver; /** @@ -41,7 +39,7 @@ import org.springframework.web.multipart.support.StandardServletMultipartResolve *

* The {@link javax.servlet.MultipartConfigElement} is a Servlet API that's used to * configure how the container handles file uploads. By default - * + * * @author Greg Turnquist * @author Josh Long */ @@ -57,25 +55,7 @@ public class MultipartAutoConfiguration { @Bean @ConditionalOnMissingBean public MultipartConfigElement multipartConfigElement() { - MultipartConfigFactory factory = new MultipartConfigFactory(); - - if (StringUtils.hasText(this.multipartProperties.getFileSizeThreshold())) { - factory.setFileSizeThreshold(this.multipartProperties.getFileSizeThreshold()); - } - - if (StringUtils.hasText(this.multipartProperties.getLocation())) { - factory.setLocation(this.multipartProperties.getLocation()); - } - - if (StringUtils.hasText(this.multipartProperties.getMaxRequestSize())) { - factory.setMaxRequestSize(this.multipartProperties.getMaxRequestSize()); - } - - if (StringUtils.hasText(this.multipartProperties.getMaxFileSize())) { - factory.setMaxFileSize(this.multipartProperties.getMaxFileSize()); - } - - return factory.createMultipartConfig(); + return this.multipartProperties.createMultipartConfig(); } @Bean @@ -83,4 +63,5 @@ public class MultipartAutoConfiguration { public StandardServletMultipartResolver multipartResolver() { return new StandardServletMultipartResolver(); } + } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartProperties.java index 91d8e49bc9..8b0e6a737b 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartProperties.java @@ -16,65 +16,99 @@ package org.springframework.boot.autoconfigure.web; +import javax.servlet.MultipartConfigElement; + +import org.springframework.boot.context.embedded.MultipartConfigFactory; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.StringUtils; /** - * Properties to be used in configuring - * a javax.servlet.MultipartConfigElement. - *

- * {@literal multipart.fileSizeThreshold} specifies the size threshold after which files will be written to disk. Default is 0, which means that the file will be written to disk immediately. - * {@literal multipart.location} specifies the directory where files will be stored. The default is "". A common value is to use the system's temporary directory, which can be obtained - * {@literal multipart.maxFileSize} specifies the maximum size permitted for uploaded files. The default is unlimited. - * {@literal multipart.maxRequestSize} specifies the maximum size allowed for {@literal multipart/form-data} requests. - *

- * These properties are ultimately passed through {@link org.springframework.boot.context.embedded.MultipartConfigFactory} - * which means you may specify the values using {@literal long} values or using more readable {@literal String} - * variants that accept {@literal KB} or {@literal MB} suffixes. - * + * Properties to be used in configuring a {@link MultipartConfigElement}. + *

+ *

+ * These properties are ultimately passed through + * {@link org.springframework.boot.context.embedded.MultipartConfigFactory} which means + * you may specify the values using {@literal long} values or using more readable + * {@literal String} variants that accept {@literal Kb} or {@literal Mb} suffixes. + * * @author Josh Long + * @since 1.1.0 */ @ConfigurationProperties(prefix = "multipart", ignoreUnknownFields = false) public class MultipartProperties { - private String maxFileSize = "1Mb"; - - private String maxRequestSize = "10Mb"; - - private String fileSizeThreshold = null; - - private String location = null; - - public String getMaxFileSize() { - return maxFileSize; - } - - public String getMaxRequestSize() { - return maxRequestSize; - } - - public String getFileSizeThreshold() { - return fileSizeThreshold; - } - - public String getLocation() { - return location; - } - - public void setMaxFileSize(String maxFileSize) { - this.maxFileSize = maxFileSize; - } - - public void setMaxRequestSize(String maxRequestSize) { - this.maxRequestSize = maxRequestSize; - } - - public void setLocation(String location) { - this.location = location; - } - - public void setFileSizeThreshold(String fileSizeThreshold) { - this.fileSizeThreshold = fileSizeThreshold; - } + private String location; + + private String maxFileSize = "1Mb"; + + private String maxRequestSize = "10Mb"; + + private String fileSizeThreshold = "0"; + + public String getMaxFileSize() { + return this.maxFileSize; + } + + public String getMaxRequestSize() { + return this.maxRequestSize; + } + + public String getFileSizeThreshold() { + return this.fileSizeThreshold; + } + + public String getLocation() { + return this.location; + } + + public void setMaxFileSize(String maxFileSize) { + this.maxFileSize = maxFileSize; + } + + public void setMaxRequestSize(String maxRequestSize) { + this.maxRequestSize = maxRequestSize; + } + + public void setLocation(String location) { + this.location = location; + } + + public void setFileSizeThreshold(String fileSizeThreshold) { + this.fileSizeThreshold = fileSizeThreshold; + } + + /** + * Create a new {@link MultipartConfigElement} using the + * @return a new {@link MultipartConfigElement} configured using there properties + */ + public MultipartConfigElement createMultipartConfig() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + if (StringUtils.hasText(this.fileSizeThreshold)) { + factory.setFileSizeThreshold(this.fileSizeThreshold); + } + if (StringUtils.hasText(this.location)) { + factory.setLocation(this.location); + } + if (StringUtils.hasText(this.maxRequestSize)) { + factory.setMaxRequestSize(this.maxRequestSize); + } + if (StringUtils.hasText(this.maxFileSize)) { + factory.setMaxFileSize(this.maxFileSize); + } + return factory.createMultipartConfig(); + } } - diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfigurationTests.java index 79fd73d4b9..a6fd7b11cb 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfigurationTests.java @@ -38,15 +38,17 @@ import org.springframework.web.multipart.support.StandardServletMultipartResolve import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; /** * Tests for {@link MultipartAutoConfiguration}. Tests an empty configuration, no * multipart configuration, and a multipart configuration (with both Jetty and Tomcat). - * + * * @author Greg Turnquist * @author Dave Syer * @author Josh Long @@ -71,10 +73,10 @@ public class MultipartAutoConfigurationTests { ContainerWithNothing.class, BaseConfiguration.class); DispatcherServlet servlet = this.context.getBean(DispatcherServlet.class); assertNotNull(servlet.getMultipartResolver()); - assertEquals(1, - this.context.getBeansOfType(StandardServletMultipartResolver.class) - .size()); - assertEquals(1, this.context.getBeansOfType(MultipartResolver.class).size()); + assertThat(this.context.getBeansOfType(StandardServletMultipartResolver.class) + .size(), equalTo(1)); + assertThat(this.context.getBeansOfType(MultipartResolver.class).size(), + equalTo(1)); } @Configuration @@ -87,10 +89,10 @@ public class MultipartAutoConfigurationTests { ContainerWithNoMultipartJetty.class, BaseConfiguration.class); DispatcherServlet servlet = this.context.getBean(DispatcherServlet.class); assertNotNull(servlet.getMultipartResolver()); - assertEquals(1, - this.context.getBeansOfType(StandardServletMultipartResolver.class) - .size()); - assertEquals(1, this.context.getBeansOfType(MultipartResolver.class).size()); + assertThat(this.context.getBeansOfType(StandardServletMultipartResolver.class) + .size(), equalTo(1)); + assertThat(this.context.getBeansOfType(MultipartResolver.class).size(), + equalTo(1)); verifyServletWorks(); } @@ -113,10 +115,10 @@ public class MultipartAutoConfigurationTests { ContainerWithNoMultipartTomcat.class, BaseConfiguration.class); DispatcherServlet servlet = this.context.getBean(DispatcherServlet.class); assertNull(servlet.getMultipartResolver()); - assertEquals(1, - this.context.getBeansOfType(StandardServletMultipartResolver.class) - .size()); - assertEquals(1, this.context.getBeansOfType(MultipartResolver.class).size()); + assertThat(this.context.getBeansOfType(StandardServletMultipartResolver.class) + .size(), equalTo(1)); + assertThat(this.context.getBeansOfType(MultipartResolver.class).size(), + equalTo(1)); verifyServletWorks(); } @@ -134,7 +136,9 @@ public class MultipartAutoConfigurationTests { public void containerWithAutomatedMultipartTomcatConfiguration() throws Exception { this.context = new AnnotationConfigEmbeddedWebApplicationContext( ContainerWithEverythingTomcat.class, BaseConfiguration.class); - new RestTemplate().getForObject("http://localhost:8080/", String.class); + new RestTemplate().getForObject("http://localhost:" + + this.context.getEmbeddedServletContainer().getPort() + "/", + String.class); this.context.getBean(MultipartConfigElement.class); assertSame(this.context.getBean(DispatcherServlet.class).getMultipartResolver(), this.context.getBean(StandardServletMultipartResolver.class)); @@ -149,8 +153,9 @@ public class MultipartAutoConfigurationTests { .addFirst(new PropertySource("test") { @Override public Object getProperty(String name) { - if (name.toLowerCase().contains("multipart.enabled")) + if (name.toLowerCase().contains("multipart.enabled")) { return "false"; + } return null; } }); @@ -162,8 +167,9 @@ public class MultipartAutoConfigurationTests { private void verifyServletWorks() { RestTemplate restTemplate = new RestTemplate(); - assertEquals(restTemplate.getForObject("http://localhost:8080/", String.class), - "Hello"); + assertEquals(restTemplate.getForObject("http://localhost:" + + this.context.getEmbeddedServletContainer().getPort() + "/", + String.class), "Hello"); } @Configuration @@ -172,6 +178,13 @@ public class MultipartAutoConfigurationTests { ServerPropertiesAutoConfiguration.class }) protected static class BaseConfiguration { + @Bean + public ServerProperties serverProperties() { + ServerProperties properties = new ServerProperties(); + properties.setPort(0); + return properties; + } + } @Configuration @@ -186,10 +199,12 @@ public class MultipartAutoConfigurationTests { WebController controller() { return new WebController(); } + } @Configuration public static class ContainerWithEverythingJetty { + @Bean MultipartConfigElement multipartConfigElement() { return new MultipartConfigElement(""); @@ -204,11 +219,13 @@ public class MultipartAutoConfigurationTests { WebController webController() { return new WebController(); } + } @Configuration @EnableWebMvc public static class ContainerWithEverythingTomcat { + @Bean MultipartConfigElement multipartConfigElement() { return new MultipartConfigElement(""); @@ -223,14 +240,18 @@ public class MultipartAutoConfigurationTests { WebController webController() { return new WebController(); } + } @Controller public static class WebController { + @RequestMapping("/") - public @ResponseBody String index() { + @ResponseBody + public String index() { return "Hello"; } + } } diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc index 01ea051abb..bfd11fdd4c 100644 --- a/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -726,22 +726,24 @@ then you can take control completely and do everything manually using See the {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`WebMvcAutoConfiguration`] source code for more details. -[[howto-multipart-file-upload-configuration]] -=== Handling Multipart File Uploads -Spring Boot embraces the Servlet 3 `javax.servlet.http.Part` API to support uploading files. By default -Spring Boot configures Spring MVC with a maximum file of 1Mb per -file and a maximum of 10Mb of file data in a single request. You may override these values, as well as the location -to which intermediate data is stored (e.g., to the `/tmp` directory) and the threshold past which data is flushed to -disk by using the properties exposed in the `MultipartAutoConfiguration` class. If you want to specify that files be unlimited, -for example, set the `multipart.maxFileSize` property to `-1`. - -The multipart support is helpful when you want to receive multipart encoded file data as a `@RequestParam`-annotated - parameter of type `MultipartFile` in a Spring MVC controller handler method. - -See the {sc-spring-boot-autoconfigure}/web/MultipartAutoConfiguration.{sc-ext}[`MultipartAutoConfiguration`] source for more details. - +[[howto-multipart-file-upload-configuration]] +=== Handling Multipart File Uploads +Spring Boot embraces the Servlet 3 `javax.servlet.http.Part` API to support uploading +files. By default Spring Boot configures Spring MVC with a maximum file of 1Mb per +file and a maximum of 10Mb of file data in a single request. You may override these +values, as well as the location to which intermediate data is stored (e.g., to the `/tmp` +directory) and the threshold past which data is flushed to disk by using the properties +exposed in the `MultipartProperties` class. If you want to specify that files be +unlimited, for example, set the `multipart.maxFileSize` property to `-1`. + +The multipart support is helpful when you want to receive multipart encoded file data as +a `@RequestParam`-annotated parameter of type `MultipartFile` in a Spring MVC controller +handler method. + +See the {sc-spring-boot-autoconfigure}/web/MultipartAutoConfiguration.{sc-ext}[`MultipartAutoConfiguration`] s +ource for more details.