Merge branch '1.5.x'
This commit is contained in:
commit
05fbd5dc46
|
@ -22,6 +22,7 @@ import java.lang.reflect.Field;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles.So
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.core.io.AbstractResource;
|
import org.springframework.core.io.AbstractResource;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.core.io.ProtocolResolver;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.springframework.core.io.UrlResource;
|
import org.springframework.core.io.UrlResource;
|
||||||
|
@ -52,6 +54,7 @@ import org.springframework.web.context.support.ServletContextResourcePatternReso
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternResolver {
|
final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternResolver {
|
||||||
|
|
||||||
|
@ -206,7 +209,20 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||||
public ResourcePatternResolver getResourcePatternResolver(
|
public ResourcePatternResolver getResourcePatternResolver(
|
||||||
ApplicationContext applicationContext, ResourceLoader resourceLoader) {
|
ApplicationContext applicationContext, ResourceLoader resourceLoader) {
|
||||||
return new PathMatchingResourcePatternResolver(resourceLoader == null
|
return new PathMatchingResourcePatternResolver(resourceLoader == null
|
||||||
? new DefaultResourceLoader() : resourceLoader);
|
? createResourceLoader(applicationContext) : resourceLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResourceLoader createResourceLoader(
|
||||||
|
ApplicationContext applicationContext) {
|
||||||
|
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
|
if (applicationContext instanceof DefaultResourceLoader) {
|
||||||
|
Collection<ProtocolResolver> protocolResolvers =
|
||||||
|
((DefaultResourceLoader) applicationContext).getProtocolResolvers();
|
||||||
|
for (ProtocolResolver protocolResolver : protocolResolvers) {
|
||||||
|
resourceLoader.addProtocolResolver(protocolResolver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resourceLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -223,13 +239,26 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||||
ApplicationContext applicationContext, ResourceLoader resourceLoader) {
|
ApplicationContext applicationContext, ResourceLoader resourceLoader) {
|
||||||
if (applicationContext instanceof WebApplicationContext) {
|
if (applicationContext instanceof WebApplicationContext) {
|
||||||
return new ServletContextResourcePatternResolver(resourceLoader == null
|
return new ServletContextResourcePatternResolver(resourceLoader == null
|
||||||
? new WebApplicationContextResourceLoader(
|
? createResourceLoader((WebApplicationContext) applicationContext)
|
||||||
(WebApplicationContext) applicationContext)
|
|
||||||
: resourceLoader);
|
: resourceLoader);
|
||||||
}
|
}
|
||||||
return super.getResourcePatternResolver(applicationContext, resourceLoader);
|
return super.getResourcePatternResolver(applicationContext, resourceLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResourceLoader createResourceLoader(
|
||||||
|
WebApplicationContext applicationContext) {
|
||||||
|
WebApplicationContextResourceLoader resourceLoader =
|
||||||
|
new WebApplicationContextResourceLoader(applicationContext);
|
||||||
|
if (applicationContext instanceof DefaultResourceLoader) {
|
||||||
|
Collection<ProtocolResolver> protocolResolvers =
|
||||||
|
((DefaultResourceLoader) applicationContext).getProtocolResolvers();
|
||||||
|
for (ProtocolResolver protocolResolver : protocolResolvers) {
|
||||||
|
resourceLoader.addProtocolResolver(protocolResolver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resourceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.boot.devtools.restart.classloader.ClassLoaderFile.Kin
|
||||||
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles;
|
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles;
|
||||||
import org.springframework.context.support.GenericApplicationContext;
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.core.io.ProtocolResolver;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.springframework.mock.web.MockServletContext;
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
@ -38,6 +39,9 @@ import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||||
import org.springframework.web.context.support.ServletContextResource;
|
import org.springframework.web.context.support.ServletContextResource;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@ -46,6 +50,7 @@ import static org.mockito.Mockito.verify;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
public class ClassLoaderFilesResourcePatternResolverTests {
|
public class ClassLoaderFilesResourcePatternResolverTests {
|
||||||
|
|
||||||
|
@ -125,6 +130,18 @@ public class ClassLoaderFilesResourcePatternResolverTests {
|
||||||
verify(resourceLoader).getResource("foo.txt");
|
verify(resourceLoader).getResource("foo.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customProtocolResolverIsUsedInNonWebApplication() throws Exception {
|
||||||
|
GenericApplicationContext context = new GenericApplicationContext();
|
||||||
|
Resource resource = mock(Resource.class);
|
||||||
|
ProtocolResolver resolver = mockProtocolResolver("foo:some-file.txt", resource);
|
||||||
|
context.addProtocolResolver(resolver);
|
||||||
|
this.resolver = new ClassLoaderFilesResourcePatternResolver(context, this.files);
|
||||||
|
Resource actual = this.resolver.getResource("foo:some-file.txt");
|
||||||
|
assertThat(actual).isSameAs(resource);
|
||||||
|
verify(resolver).resolve(eq("foo:some-file.txt"), any(ResourceLoader.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customResourceLoaderIsUsedInWebApplication() throws Exception {
|
public void customResourceLoaderIsUsedInWebApplication() throws Exception {
|
||||||
GenericWebApplicationContext context = new GenericWebApplicationContext(
|
GenericWebApplicationContext context = new GenericWebApplicationContext(
|
||||||
|
@ -136,6 +153,26 @@ public class ClassLoaderFilesResourcePatternResolverTests {
|
||||||
verify(resourceLoader).getResource("foo.txt");
|
verify(resourceLoader).getResource("foo.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customProtocolResolverIsUsedInWebApplication() throws Exception {
|
||||||
|
GenericWebApplicationContext context = new GenericWebApplicationContext(
|
||||||
|
new MockServletContext());
|
||||||
|
Resource resource = mock(Resource.class);
|
||||||
|
ProtocolResolver resolver = mockProtocolResolver("foo:some-file.txt", resource);
|
||||||
|
context.addProtocolResolver(resolver);
|
||||||
|
this.resolver = new ClassLoaderFilesResourcePatternResolver(context, this.files);
|
||||||
|
Resource actual = this.resolver.getResource("foo:some-file.txt");
|
||||||
|
assertThat(actual).isSameAs(resource);
|
||||||
|
verify(resolver).resolve(eq("foo:some-file.txt"), any(ResourceLoader.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProtocolResolver mockProtocolResolver(String path, Resource resource) {
|
||||||
|
ProtocolResolver resolver = mock(ProtocolResolver.class);
|
||||||
|
given(resolver.resolve(eq(path), any(ResourceLoader.class)))
|
||||||
|
.willReturn(resource);
|
||||||
|
return resolver;
|
||||||
|
}
|
||||||
|
|
||||||
private File createFile(File folder, String name) throws IOException {
|
private File createFile(File folder, String name) throws IOException {
|
||||||
File file = new File(folder, name);
|
File file = new File(folder, name);
|
||||||
FileCopyUtils.copy("test".getBytes(), file);
|
FileCopyUtils.copy("test".getBytes(), file);
|
||||||
|
|
|
@ -777,6 +777,10 @@ NOTE: When deciding if an entry on the classpath should trigger a restart when i
|
||||||
DevTools automatically ignores projects named `spring-boot`, `spring-boot-devtools`,
|
DevTools automatically ignores projects named `spring-boot`, `spring-boot-devtools`,
|
||||||
`spring-boot-autoconfigure`, `spring-boot-actuator`, and `spring-boot-starter`.
|
`spring-boot-autoconfigure`, `spring-boot-actuator`, and `spring-boot-starter`.
|
||||||
|
|
||||||
|
NOTE: DevTools needs to customize the `ResourceLoader` used by the `ApplicationContext`:
|
||||||
|
if your application provides one already, it is going to be wrapped. Direct override of
|
||||||
|
the `getResource` method on the `ApplicationContext` is not supported.
|
||||||
|
|
||||||
[[using-spring-boot-restart-vs-reload]]
|
[[using-spring-boot-restart-vs-reload]]
|
||||||
.Restart vs Reload
|
.Restart vs Reload
|
||||||
****
|
****
|
||||||
|
|
Loading…
Reference in New Issue