diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsProperties.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsProperties.java index 34eec348857..ac301c59546 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsProperties.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsProperties.java @@ -22,6 +22,7 @@ import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.util.StringUtils; /** * Configuration properties for developer tools. @@ -71,10 +72,15 @@ public class DevToolsProperties { private boolean enabled = true; /** - * Patterns that should be excluding for triggering a full restart. + * Patterns that should be excluded from triggering a full restart. */ private String exclude = DEFAULT_RESTART_EXCLUDES; + /** + * Additional patterns that should be excluded from triggering a full restart. + */ + private String additionalExclude; + /** * Amount of time (in milliseconds) to wait between polling for classpath changes. */ @@ -105,6 +111,17 @@ public class DevToolsProperties { this.enabled = enabled; } + public String[] getAllExclude() { + List allExclude = new ArrayList(); + if (StringUtils.hasText(this.exclude)) { + allExclude.addAll(StringUtils.commaDelimitedListToSet(this.exclude)); + } + if (StringUtils.hasText(this.additionalExclude)) { + allExclude.addAll(StringUtils.commaDelimitedListToSet(this.additionalExclude)); + } + return allExclude.toArray(new String[allExclude.size()]); + } + public String getExclude() { return this.exclude; } @@ -113,6 +130,14 @@ public class DevToolsProperties { this.exclude = exclude; } + public String getAdditionalExclude() { + return this.additionalExclude; + } + + public void setAdditionalExclude(String additionalExclude) { + this.additionalExclude = additionalExclude; + } + public long getPollInterval() { return this.pollInterval; } diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java index 482f5c58356..b113708acec 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java @@ -123,7 +123,7 @@ public class LocalDevToolsAutoConfiguration { @ConditionalOnMissingBean public ClassPathRestartStrategy classPathRestartStrategy() { return new PatternClassPathRestartStrategy(this.properties.getRestart() - .getExclude()); + .getAllExclude()); } @Bean diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/PatternClassPathRestartStrategy.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/PatternClassPathRestartStrategy.java index a2e4b671186..03a440193e0 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/PatternClassPathRestartStrategy.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/PatternClassPathRestartStrategy.java @@ -33,9 +33,12 @@ public class PatternClassPathRestartStrategy implements ClassPathRestartStrategy private final String[] excludePatterns; + public PatternClassPathRestartStrategy(String[] excludePatterns) { + this.excludePatterns = excludePatterns; + } + public PatternClassPathRestartStrategy(String excludePatterns) { - this.excludePatterns = StringUtils - .commaDelimitedListToStringArray(excludePatterns); + this(StringUtils.commaDelimitedListToStringArray(excludePatterns)); } @Override diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java index 65479679cdd..97b503f92d4 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java @@ -214,7 +214,7 @@ public class RemoteClientConfiguration { @Bean public ClassPathRestartStrategy classPathRestartStrategy() { return new PatternClassPathRestartStrategy(this.properties.getRestart() - .getExclude()); + .getAllExclude()); } @Bean diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsPropertiesTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsPropertiesTests.java new file mode 100644 index 00000000000..a639c3d6f9e --- /dev/null +++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsPropertiesTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2015 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.devtools.autoconfigure; + +import org.junit.Test; + +import static org.hamcrest.Matchers.arrayContaining; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link DevToolsProperties}. + * + * @author Stephane Nicoll + */ +public class DevToolsPropertiesTests { + + private final DevToolsProperties devToolsProperties = new DevToolsProperties(); + + @Test + public void additionalExcludeKeepsDefaults() { + DevToolsProperties.Restart restart = this.devToolsProperties.getRestart(); + restart.setAdditionalExclude("foo/**,bar/**"); + assertThat(restart.getAllExclude(), arrayContaining("META-INF/maven/**", + "META-INF/resources/**", "resources/**", "static/**", "public/**", + "templates/**", "foo/**", "bar/**")); + } + + @Test + public void additionalExcludeNoDefault() { + DevToolsProperties.Restart restart = this.devToolsProperties.getRestart(); + restart.setExclude(""); + restart.setAdditionalExclude("foo/**,bar/**"); + assertThat(restart.getAllExclude(), arrayContaining("foo/**", "bar/**")); + } + + @Test + public void additionalExcludeCustomDefault() { + DevToolsProperties.Restart restart = this.devToolsProperties.getRestart(); + restart.setExclude("biz/**"); + restart.setAdditionalExclude("foo/**,bar/**"); + assertThat(restart.getAllExclude(), arrayContaining("biz/**", "foo/**", "bar/**")); + } + +} diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 33b2281787e..162338111f9 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -627,7 +627,8 @@ content into your application; rather pick only the properties that you need. # DEVTOOLS ({sc-spring-boot-devtools}/autoconfigure/DevToolsProperties.{sc-ext}[DevToolsProperties]) spring.devtools.restart.additional-paths= # additional paths to watch for changes spring.devtools.restart.enabled=true # enable automatic restart - spring.devtools.restart.exclude= # patterns that should be excluding for triggering a full restart + spring.devtools.restart.exclude= # patterns that should be excluded from triggering a full restart + spring.devtools.restart.additional-exclude= # additional patterns that should be excluded from triggering a full restart spring.devtools.restart.poll-interval= # amount of time (in milliseconds) to wait between polling for classpath changes spring.devtools.restart.quiet-period= # amount of quiet time (in milliseconds) required without any classpath changes before a restart is triggered spring.devtools.restart.trigger-file= # name of a specific file that when changed will trigger the restart diff --git a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc index ee92ed4921a..29d5fe0f1a3 100644 --- a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc +++ b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc @@ -910,6 +910,8 @@ you can use the `spring.devtools.restart.exclude` property. For example, to excl spring.devtools.restart.exclude=static/**,public/** ---- +TIP: if you want to keep those defaults and _add_ additional exclusions, use the +`spring.devtools.restart.exclude.additional-exclude` property instead. [[using-boot-devtools-restart-additional-paths]]