Merge branch '2.0.x'
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -19,7 +19,9 @@
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
<property>
|
||||
<name>!disable-spring-boot-default-profile</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<spring-javaformat.version>0.0.3</spring-javaformat.version>
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.ExposeExcludePropertyEndpointFilter;
|
||||
@@ -30,11 +27,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPathProvider;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
@@ -72,27 +68,13 @@ public class ServletEndpointManagementContextConfiguration {
|
||||
public ServletEndpointRegistrar servletEndpointRegistrar(
|
||||
WebEndpointProperties properties,
|
||||
ServletEndpointsSupplier servletEndpointsSupplier) {
|
||||
DispatcherServletPathProvider servletPathProvider = this.context
|
||||
.getBean(DispatcherServletPathProvider.class);
|
||||
Set<String> cleanedPaths = getServletPaths(properties, servletPathProvider);
|
||||
return new ServletEndpointRegistrar(cleanedPaths,
|
||||
DispatcherServletPath dispatcherServletPath = this.context
|
||||
.getBean(DispatcherServletPath.class);
|
||||
return new ServletEndpointRegistrar(
|
||||
dispatcherServletPath.getRelativePath(properties.getBasePath()),
|
||||
servletEndpointsSupplier.getEndpoints());
|
||||
}
|
||||
|
||||
private Set<String> getServletPaths(WebEndpointProperties properties,
|
||||
DispatcherServletPathProvider servletPathProvider) {
|
||||
return servletPathProvider.getServletPaths().stream()
|
||||
.map((p) -> cleanServletPath(p) + properties.getBasePath())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private String cleanServletPath(String servletPath) {
|
||||
if (StringUtils.hasText(servletPath) && servletPath.endsWith("/")) {
|
||||
return servletPath.substring(0, servletPath.length() - 1);
|
||||
}
|
||||
return servletPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPathProvider;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.boot.security.servlet.ApplicationContextRequestMatcher;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
@@ -137,23 +137,20 @@ public final class EndpointRequest {
|
||||
|
||||
private RequestMatcher createDelegate(WebApplicationContext context) {
|
||||
try {
|
||||
Set<String> servletPaths = getServletPaths(context);
|
||||
RequestMatcherFactory requestMatcherFactory = new RequestMatcherFactory(
|
||||
servletPaths);
|
||||
return createDelegate(context, requestMatcherFactory);
|
||||
String pathPrefix = getPathPrefix(context);
|
||||
return createDelegate(context, new RequestMatcherFactory(pathPrefix));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return EMPTY_MATCHER;
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> getServletPaths(WebApplicationContext context) {
|
||||
private String getPathPrefix(WebApplicationContext context) {
|
||||
try {
|
||||
return context.getBean(DispatcherServletPathProvider.class)
|
||||
.getServletPaths();
|
||||
return context.getBean(DispatcherServletPath.class).getPrefix();
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return Collections.singleton("");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +222,7 @@ public final class EndpointRequest {
|
||||
requestMatcherFactory, paths);
|
||||
if (this.includeLinks
|
||||
&& StringUtils.hasText(pathMappedEndpoints.getBasePath())) {
|
||||
delegateMatchers.addAll(
|
||||
delegateMatchers.add(
|
||||
requestMatcherFactory.antPath(pathMappedEndpoints.getBasePath()));
|
||||
}
|
||||
return new OrRequestMatcher(delegateMatchers);
|
||||
@@ -258,8 +255,7 @@ public final class EndpointRequest {
|
||||
private List<RequestMatcher> getDelegateMatchers(
|
||||
RequestMatcherFactory requestMatcherFactory, Set<String> paths) {
|
||||
return paths.stream()
|
||||
.flatMap(
|
||||
(path) -> requestMatcherFactory.antPath(path, "/**").stream())
|
||||
.map((path) -> requestMatcherFactory.antPath(path, "/**"))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -276,9 +272,7 @@ public final class EndpointRequest {
|
||||
WebEndpointProperties properties = context
|
||||
.getBean(WebEndpointProperties.class);
|
||||
if (StringUtils.hasText(properties.getBasePath())) {
|
||||
List<RequestMatcher> matchers = requestMatcherFactory
|
||||
.antPath(properties.getBasePath());
|
||||
return new OrRequestMatcher(matchers);
|
||||
return requestMatcherFactory.antPath(properties.getBasePath());
|
||||
}
|
||||
return EMPTY_MATCHER;
|
||||
}
|
||||
@@ -290,19 +284,18 @@ public final class EndpointRequest {
|
||||
*/
|
||||
private static class RequestMatcherFactory {
|
||||
|
||||
private final Set<String> servletPaths = new LinkedHashSet<>();
|
||||
private final String prefix;
|
||||
|
||||
RequestMatcherFactory(Set<String> servletPaths) {
|
||||
this.servletPaths.addAll(servletPaths);
|
||||
RequestMatcherFactory(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
List<RequestMatcher> antPath(String... parts) {
|
||||
return this.servletPaths.stream()
|
||||
.map((p) -> (StringUtils.hasText(p) && !p.equals("/") ? p : ""))
|
||||
.distinct()
|
||||
.map((path) -> Arrays.stream(parts)
|
||||
.collect(Collectors.joining("", path, "")))
|
||||
.map(AntPathRequestMatcher::new).collect(Collectors.toList());
|
||||
public RequestMatcher antPath(String... parts) {
|
||||
String pattern = this.prefix;
|
||||
for (String part : parts) {
|
||||
pattern += part;
|
||||
}
|
||||
return new AntPathRequestMatcher(pattern);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,12 +24,11 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
/**
|
||||
* Composite {@link HandlerExceptionResolver}.
|
||||
* Composite {@link HandlerMapping}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.web.servlet;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType;
|
||||
@@ -27,7 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPathProvider;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.error.ErrorAttributes;
|
||||
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -72,6 +70,12 @@ class WebMvcEndpointChildContextConfiguration {
|
||||
return dispatcherServlet;
|
||||
}
|
||||
|
||||
@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
|
||||
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(
|
||||
DispatcherServlet dispatcherServlet) {
|
||||
return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
|
||||
}
|
||||
|
||||
@Bean(name = DispatcherServlet.HANDLER_MAPPING_BEAN_NAME)
|
||||
public CompositeHandlerMapping compositeHandlerMapping() {
|
||||
return new CompositeHandlerMapping();
|
||||
@@ -95,9 +99,4 @@ class WebMvcEndpointChildContextConfiguration {
|
||||
return new OrderedRequestContextFilter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DispatcherServletPathProvider childDispatcherServletPathProvider() {
|
||||
return () -> Collections.singleton("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,15 +17,13 @@
|
||||
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.web.ServletEndpointRegistrar;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPathProvider;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
@@ -50,22 +48,18 @@ public class ServletEndpointManagementContextConfigurationTests {
|
||||
.withUserConfiguration(TestConfig.class);
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void contextShouldContainServletEndpointRegistrar() {
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(ResourceConfig.class);
|
||||
this.contextRunner.withClassLoader(classLoader).run((context) -> {
|
||||
assertThat(context).hasSingleBean(ServletEndpointRegistrar.class);
|
||||
ServletEndpointRegistrar bean = context
|
||||
.getBean(ServletEndpointRegistrar.class);
|
||||
Set<String> basePaths = (Set<String>) ReflectionTestUtils.getField(bean,
|
||||
"basePaths");
|
||||
assertThat(basePaths).containsExactlyInAnyOrder("/test/actuator", "/actuator",
|
||||
"/foo/actuator");
|
||||
String basePath = (String) ReflectionTestUtils.getField(bean, "basePath");
|
||||
assertThat(basePath).isEqualTo("/test/actuator");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void servletPathShouldNotAffectJerseyConfiguration() {
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(
|
||||
DispatcherServlet.class);
|
||||
@@ -73,9 +67,8 @@ public class ServletEndpointManagementContextConfigurationTests {
|
||||
assertThat(context).hasSingleBean(ServletEndpointRegistrar.class);
|
||||
ServletEndpointRegistrar bean = context
|
||||
.getBean(ServletEndpointRegistrar.class);
|
||||
Set<String> basePaths = (Set<String>) ReflectionTestUtils.getField(bean,
|
||||
"basePaths");
|
||||
assertThat(basePaths).containsExactly("/actuator");
|
||||
String basePath = (String) ReflectionTestUtils.getField(bean, "basePath");
|
||||
assertThat(basePath).isEqualTo("/actuator");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -97,14 +90,8 @@ public class ServletEndpointManagementContextConfigurationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DispatcherServletPathProvider servletPathProvider() {
|
||||
return () -> {
|
||||
Set<String> paths = new LinkedHashSet<>();
|
||||
paths.add("/");
|
||||
paths.add("/test");
|
||||
paths.add("/foo/");
|
||||
return paths;
|
||||
};
|
||||
public DispatcherServletPath dispatcherServletPath() {
|
||||
return () -> "/test";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.springframework.boot.actuate.autoconfigure.security.servlet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -33,7 +31,7 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpoint;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPathProvider;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
@@ -78,12 +76,11 @@ public class EndpointRequestTests {
|
||||
@Test
|
||||
public void toAnyEndpointWhenServletPathNotEmptyShouldMatch() {
|
||||
RequestMatcher matcher = EndpointRequest.toAnyEndpoint();
|
||||
assertMatcher(matcher, "/actuator", "/spring", "/admin")
|
||||
.matches(Arrays.asList("/spring", "/admin"), "/actuator/foo");
|
||||
assertMatcher(matcher, "/actuator", "/spring", "/admin")
|
||||
.matches(Arrays.asList("/spring", "/admin"), "/actuator/bar");
|
||||
assertMatcher(matcher, "/actuator", "/spring").matches(Arrays.asList("/spring"),
|
||||
"/actuator");
|
||||
assertMatcher(matcher, "/actuator", "/spring").matches("/spring",
|
||||
"/actuator/foo");
|
||||
assertMatcher(matcher, "/actuator", "/spring").matches("/spring",
|
||||
"/actuator/bar");
|
||||
assertMatcher(matcher, "/actuator", "/spring").matches("/spring", "/actuator");
|
||||
assertMatcher(matcher, "/actuator", "/spring").doesNotMatch("/spring",
|
||||
"/actuator/baz");
|
||||
assertMatcher(matcher, "/actuator", "/spring").doesNotMatch("", "/actuator/foo");
|
||||
@@ -92,10 +89,10 @@ public class EndpointRequestTests {
|
||||
@Test
|
||||
public void toAnyEndpointWhenDispatcherServletPathProviderNotAvailableUsesEmptyPath() {
|
||||
RequestMatcher matcher = EndpointRequest.toAnyEndpoint();
|
||||
assertMatcher(matcher, "/actuator", (String) null).matches("/actuator/foo");
|
||||
assertMatcher(matcher, "/actuator", (String) null).matches("/actuator/bar");
|
||||
assertMatcher(matcher, "/actuator", (String) null).matches("/actuator");
|
||||
assertMatcher(matcher, "/actuator", (String) null).doesNotMatch("/actuator/baz");
|
||||
assertMatcher(matcher, "/actuator", null).matches("/actuator/foo");
|
||||
assertMatcher(matcher, "/actuator", null).matches("/actuator/bar");
|
||||
assertMatcher(matcher, "/actuator", null).matches("/actuator");
|
||||
assertMatcher(matcher, "/actuator", null).doesNotMatch("/actuator/baz");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -222,8 +219,8 @@ public class EndpointRequestTests {
|
||||
}
|
||||
|
||||
private RequestMatcherAssert assertMatcher(RequestMatcher matcher, String basePath,
|
||||
String... servletPaths) {
|
||||
return assertMatcher(matcher, mockPathMappedEndpoints(basePath), servletPaths);
|
||||
String servletPath) {
|
||||
return assertMatcher(matcher, mockPathMappedEndpoints(basePath), servletPath);
|
||||
}
|
||||
|
||||
private PathMappedEndpoints mockPathMappedEndpoints(String basePath) {
|
||||
@@ -246,7 +243,7 @@ public class EndpointRequestTests {
|
||||
}
|
||||
|
||||
private RequestMatcherAssert assertMatcher(RequestMatcher matcher,
|
||||
PathMappedEndpoints pathMappedEndpoints, String... servletPaths) {
|
||||
PathMappedEndpoints pathMappedEndpoints, String dispatcherServletPath) {
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
context.registerBean(WebEndpointProperties.class);
|
||||
if (pathMappedEndpoints != null) {
|
||||
@@ -257,10 +254,9 @@ public class EndpointRequestTests {
|
||||
properties.setBasePath(pathMappedEndpoints.getBasePath());
|
||||
}
|
||||
}
|
||||
if (servletPaths != null) {
|
||||
DispatcherServletPathProvider pathProvider = () -> new LinkedHashSet<>(
|
||||
Arrays.asList(servletPaths));
|
||||
context.registerBean(DispatcherServletPathProvider.class, () -> pathProvider);
|
||||
if (dispatcherServletPath != null) {
|
||||
DispatcherServletPath path = () -> dispatcherServletPath;
|
||||
context.registerBean(DispatcherServletPath.class, () -> path);
|
||||
}
|
||||
return assertThat(new RequestMatcherAssert(context, matcher));
|
||||
}
|
||||
@@ -280,8 +276,8 @@ public class EndpointRequestTests {
|
||||
matches(mockRequest(servletPath));
|
||||
}
|
||||
|
||||
public void matches(List<String> servletPaths, String pathInfo) {
|
||||
servletPaths.forEach((p) -> matches(mockRequest(p, pathInfo)));
|
||||
public void matches(String servletPath, String pathInfo) {
|
||||
matches(mockRequest(servletPath, pathInfo));
|
||||
}
|
||||
|
||||
private void matches(HttpServletRequest request) {
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.web.servlet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPathProvider;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -64,12 +64,12 @@ public class WebMvcEndpointChildContextConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextShouldConfigureDispatcherServletPathProviderWithEmptyPath() {
|
||||
public void contextShouldConfigureDispatcherServletPathWithRootPath() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(WebMvcEndpointChildContextConfiguration.class)
|
||||
.run((context) -> assertThat(context
|
||||
.getBean(DispatcherServletPathProvider.class).getServletPaths())
|
||||
.containsExactly(""));
|
||||
.run((context) -> assertThat(
|
||||
context.getBean(DispatcherServletPath.class).getPath())
|
||||
.isEqualTo("/"));
|
||||
}
|
||||
|
||||
static class ExistingConfig {
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.web;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
@@ -30,7 +27,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link ServletContextInitializer} to register {@link ExposableServletEndpoint servlet
|
||||
@@ -44,24 +40,14 @@ public class ServletEndpointRegistrar implements ServletContextInitializer {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ServletEndpointRegistrar.class);
|
||||
|
||||
private final Set<String> basePaths = new LinkedHashSet<>();
|
||||
private final String basePath;
|
||||
|
||||
private final Collection<ExposableServletEndpoint> servletEndpoints;
|
||||
|
||||
public ServletEndpointRegistrar(String basePath,
|
||||
Collection<ExposableServletEndpoint> servletEndpoints) {
|
||||
Assert.notNull(servletEndpoints, "ServletEndpoints must not be null");
|
||||
this.basePaths.add((basePath != null ? basePath : ""));
|
||||
this.servletEndpoints = servletEndpoints;
|
||||
}
|
||||
|
||||
public ServletEndpointRegistrar(Set<String> basePaths,
|
||||
Collection<ExposableServletEndpoint> servletEndpoints) {
|
||||
Assert.notNull(servletEndpoints, "ServletEndpoints must not be null");
|
||||
this.basePaths.addAll(basePaths);
|
||||
if (CollectionUtils.isEmpty(this.basePaths)) {
|
||||
this.basePaths.add("");
|
||||
}
|
||||
this.basePath = (basePath != null ? basePath : "");
|
||||
this.servletEndpoints = servletEndpoints;
|
||||
}
|
||||
|
||||
@@ -74,24 +60,14 @@ public class ServletEndpointRegistrar implements ServletContextInitializer {
|
||||
private void register(ServletContext servletContext,
|
||||
ExposableServletEndpoint endpoint) {
|
||||
String name = endpoint.getId() + "-actuator-endpoint";
|
||||
String path = this.basePath + "/" + endpoint.getRootPath();
|
||||
String urlMapping = (path.endsWith("/") ? path + "*" : path + "/*");
|
||||
EndpointServlet endpointServlet = endpoint.getEndpointServlet();
|
||||
Dynamic registration = servletContext.addServlet(name,
|
||||
endpointServlet.getServlet());
|
||||
String[] urlMappings = getUrlMappings(endpoint.getRootPath());
|
||||
registration.addMapping(urlMappings);
|
||||
if (logger.isInfoEnabled()) {
|
||||
Arrays.stream(urlMappings).forEach(
|
||||
(mapping) -> logger.info("Registered '" + mapping + "' to " + name));
|
||||
}
|
||||
registration.addMapping(urlMapping);
|
||||
registration.setInitParameters(endpointServlet.getInitParameters());
|
||||
}
|
||||
|
||||
private String[] getUrlMappings(String endpointPath) {
|
||||
return this.basePaths.stream()
|
||||
.map((basePath) -> (basePath != null ? basePath + "/" + endpointPath
|
||||
: "/" + endpointPath))
|
||||
.distinct().map((path) -> (path.endsWith("/") ? path + "*" : path + "/*"))
|
||||
.toArray(String[]::new);
|
||||
logger.info("Registered '" + path + "' to " + name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.springframework.boot.actuate.endpoint.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.GenericServlet;
|
||||
import javax.servlet.Servlet;
|
||||
@@ -49,7 +47,6 @@ import static org.mockito.Mockito.verify;
|
||||
* Tests for {@link ServletEndpointRegistrar}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class ServletEndpointRegistrarTests {
|
||||
|
||||
@@ -76,14 +73,14 @@ public class ServletEndpointRegistrarTests {
|
||||
public void createWhenServletEndpointsIsNullShouldThrowException() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("ServletEndpoints must not be null");
|
||||
new ServletEndpointRegistrar((String) null, null);
|
||||
new ServletEndpointRegistrar(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartupShouldRegisterServlets() throws Exception {
|
||||
ExposableServletEndpoint endpoint = mockEndpoint(
|
||||
new EndpointServlet(TestServlet.class));
|
||||
ServletEndpointRegistrar registrar = new ServletEndpointRegistrar((String) null,
|
||||
ServletEndpointRegistrar registrar = new ServletEndpointRegistrar(null,
|
||||
Collections.singleton(endpoint));
|
||||
registrar.onStartup(this.servletContext);
|
||||
verify(this.servletContext).addServlet(eq("test-actuator-endpoint"),
|
||||
@@ -105,64 +102,6 @@ public class ServletEndpointRegistrarTests {
|
||||
verify(this.dynamic).addMapping("/actuator/test/*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartupWhenHasMultipleBasePathsShouldIncludeAllBasePaths()
|
||||
throws Exception {
|
||||
ExposableServletEndpoint endpoint = mockEndpoint(
|
||||
new EndpointServlet(TestServlet.class));
|
||||
Set<String> basePaths = new LinkedHashSet<>();
|
||||
basePaths.add("/actuator");
|
||||
basePaths.add("/admin");
|
||||
basePaths.add("/application");
|
||||
ServletEndpointRegistrar registrar = new ServletEndpointRegistrar(basePaths,
|
||||
Collections.singleton(endpoint));
|
||||
registrar.onStartup(this.servletContext);
|
||||
verify(this.servletContext).addServlet(eq("test-actuator-endpoint"),
|
||||
this.servlet.capture());
|
||||
assertThat(this.servlet.getValue()).isInstanceOf(TestServlet.class);
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
verify(this.dynamic).addMapping(captor.capture());
|
||||
assertThat(captor.getAllValues()).containsExactlyInAnyOrder("/application/test/*",
|
||||
"/admin/test/*", "/actuator/test/*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartupWhenHasEmptyBasePathsShouldIncludeRoot() throws Exception {
|
||||
ExposableServletEndpoint endpoint = mockEndpoint(
|
||||
new EndpointServlet(TestServlet.class));
|
||||
Set<String> basePaths = Collections.emptySet();
|
||||
ServletEndpointRegistrar registrar = new ServletEndpointRegistrar(basePaths,
|
||||
Collections.singleton(endpoint));
|
||||
registrar.onStartup(this.servletContext);
|
||||
verify(this.dynamic).addMapping("/test/*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartupWhenHasBasePathsHasNullValueShouldIncludeRoot()
|
||||
throws Exception {
|
||||
ExposableServletEndpoint endpoint = mockEndpoint(
|
||||
new EndpointServlet(TestServlet.class));
|
||||
Set<String> basePaths = new LinkedHashSet<>();
|
||||
basePaths.add(null);
|
||||
ServletEndpointRegistrar registrar = new ServletEndpointRegistrar(basePaths,
|
||||
Collections.singleton(endpoint));
|
||||
registrar.onStartup(this.servletContext);
|
||||
verify(this.dynamic).addMapping("/test/*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartupWhenDuplicateValuesShouldIncludeDistinct() throws Exception {
|
||||
ExposableServletEndpoint endpoint = mockEndpoint(
|
||||
new EndpointServlet(TestServlet.class));
|
||||
Set<String> basePaths = new LinkedHashSet<>();
|
||||
basePaths.add("");
|
||||
basePaths.add(null);
|
||||
ServletEndpointRegistrar registrar = new ServletEndpointRegistrar(basePaths,
|
||||
Collections.singleton(endpoint));
|
||||
registrar.onStartup(this.servletContext);
|
||||
verify(this.dynamic).addMapping("/test/*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStartupWhenHasInitParametersShouldRegisterInitParameters()
|
||||
throws Exception {
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.util.stream.Stream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.boot.autoconfigure.security.StaticResourceLocation;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.boot.security.servlet.ApplicationContextRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
@@ -96,14 +96,14 @@ public final class StaticResourceRequest {
|
||||
* Locations}.
|
||||
*/
|
||||
public static final class StaticResourceRequestMatcher
|
||||
extends ApplicationContextRequestMatcher<WebMvcProperties> {
|
||||
extends ApplicationContextRequestMatcher<DispatcherServletPath> {
|
||||
|
||||
private final Set<StaticResourceLocation> locations;
|
||||
|
||||
private volatile RequestMatcher delegate;
|
||||
|
||||
private StaticResourceRequestMatcher(Set<StaticResourceLocation> locations) {
|
||||
super(WebMvcProperties.class);
|
||||
super(DispatcherServletPath.class);
|
||||
this.locations = locations;
|
||||
}
|
||||
|
||||
@@ -134,25 +134,26 @@ public final class StaticResourceRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialized(Supplier<WebMvcProperties> serverProperties) {
|
||||
protected void initialized(
|
||||
Supplier<DispatcherServletPath> dispatcherServletPath) {
|
||||
this.delegate = new OrRequestMatcher(
|
||||
getDelegateMatchers(serverProperties.get()));
|
||||
getDelegateMatchers(dispatcherServletPath.get()));
|
||||
}
|
||||
|
||||
private List<RequestMatcher> getDelegateMatchers(
|
||||
WebMvcProperties serverProperties) {
|
||||
return getPatterns(serverProperties).map(AntPathRequestMatcher::new)
|
||||
DispatcherServletPath dispatcherServletPath) {
|
||||
return getPatterns(dispatcherServletPath).map(AntPathRequestMatcher::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Stream<String> getPatterns(WebMvcProperties serverProperties) {
|
||||
private Stream<String> getPatterns(DispatcherServletPath dispatcherServletPath) {
|
||||
return this.locations.stream().flatMap(StaticResourceLocation::getPatterns)
|
||||
.map(serverProperties.getServlet()::getPath);
|
||||
.map(dispatcherServletPath::getRelativePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matches(HttpServletRequest request,
|
||||
Supplier<WebMvcProperties> context) {
|
||||
Supplier<DispatcherServletPath> context) {
|
||||
return this.delegate.matches(request);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.boot.autoconfigure.web.servlet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.MultipartConfigElement;
|
||||
@@ -34,7 +33,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
@@ -134,11 +132,10 @@ public class DispatcherServletAutoConfiguration {
|
||||
|
||||
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
|
||||
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
|
||||
public ServletRegistrationBean<DispatcherServlet> dispatcherServletRegistration(
|
||||
public DispatcherServletRegistrationBean dispatcherServletRegistration(
|
||||
DispatcherServlet dispatcherServlet) {
|
||||
ServletRegistrationBean<DispatcherServlet> registration = new ServletRegistrationBean<>(
|
||||
dispatcherServlet,
|
||||
this.webMvcProperties.getServlet().getServletMapping());
|
||||
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(
|
||||
dispatcherServlet, this.webMvcProperties.getServlet().getPath());
|
||||
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
|
||||
registration.setLoadOnStartup(
|
||||
this.webMvcProperties.getServlet().getLoadOnStartup());
|
||||
@@ -148,15 +145,6 @@ public class DispatcherServletAutoConfiguration {
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(DispatcherServletPathProvider.class)
|
||||
@ConditionalOnSingleCandidate(DispatcherServlet.class)
|
||||
public DispatcherServletPathProvider dispatcherServletPathProvider() {
|
||||
return () -> Collections.singleton(
|
||||
DispatcherServletRegistrationConfiguration.this.webMvcProperties
|
||||
.getServlet().getPath());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 10)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.autoconfigure.web.servlet;
|
||||
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* Interface that can be used by auto-configurations that need path details for the
|
||||
* {@link DispatcherServletAutoConfiguration#DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME
|
||||
* default} {@link DispatcherServlet}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.4
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface DispatcherServletPath {
|
||||
|
||||
/**
|
||||
* Returns the configured path of the dispatcher servlet.
|
||||
* @return the configured path
|
||||
*/
|
||||
String getPath();
|
||||
|
||||
/**
|
||||
* Return a form of the given path that's relative to the dispatcher servlet path.
|
||||
* @param path the path to make relative
|
||||
* @return the relative path
|
||||
*/
|
||||
default String getRelativePath(String path) {
|
||||
String prefix = getPrefix();
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
return prefix + path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a cleaned up version of the path that can be used as a prefix for URLs. The
|
||||
* resulting path will have path will not have a trailing slash.
|
||||
* @return the prefix
|
||||
* @see #getRelativePath(String)
|
||||
*/
|
||||
default String getPrefix() {
|
||||
String result = getPath();
|
||||
int index = result.indexOf('*');
|
||||
if (index != -1) {
|
||||
result = result.substring(0, index);
|
||||
}
|
||||
if (result.endsWith("/")) {
|
||||
result = result.substring(0, result.length() - 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a URL mapping pattern that can be used with a
|
||||
* {@link ServletRegistrationBean} to map the dispatcher servlet.
|
||||
* @return the path as a servlet URL mapping
|
||||
*/
|
||||
default String getServletUrlMapping() {
|
||||
if (getPath().equals("") || getPath().equals("/")) {
|
||||
return "/";
|
||||
}
|
||||
if (getPath().contains("*")) {
|
||||
return getPath();
|
||||
}
|
||||
if (getPath().endsWith("/")) {
|
||||
return getPath() + "*";
|
||||
}
|
||||
return getPath() + "/*";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.web.servlet;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
@@ -26,10 +24,13 @@ import org.springframework.web.servlet.DispatcherServlet;
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.2
|
||||
* @deprecated since 2.0.4 in favor of {@link DispatcherServletPath} and
|
||||
* {@link DispatcherServletRegistrationBean}
|
||||
*/
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
public interface DispatcherServletPathProvider {
|
||||
|
||||
Set<String> getServletPaths();
|
||||
String getServletPath();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.autoconfigure.web.servlet;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* {@link ServletRegistrationBean} for the auto-configured {@link DispatcherServlet}. Both
|
||||
* registeres the servlet and exposes {@link DispatcherServletPath} information.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public class DispatcherServletRegistrationBean extends
|
||||
ServletRegistrationBean<DispatcherServlet> implements DispatcherServletPath {
|
||||
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* Create a new {@link DispatcherServletRegistrationBean} instance for the given
|
||||
* servlet and path.
|
||||
* @param servlet the dispatcher servlet
|
||||
* @param path the dispatcher servlet path
|
||||
*/
|
||||
public DispatcherServletRegistrationBean(DispatcherServlet servlet, String path) {
|
||||
super(servlet);
|
||||
Assert.notNull(path, "Path must not be null");
|
||||
this.path = path;
|
||||
super.addUrlMappings(getServletUrlMapping());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUrlMappings(Collection<String> urlMappings) {
|
||||
throw new UnsupportedOperationException(
|
||||
"URL Mapping cannot be changed on a DispatcherServlet registration");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addUrlMappings(String... urlMappings) {
|
||||
throw new UnsupportedOperationException(
|
||||
"URL Mapping cannot be changed on a DispatcherServlet registration");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -49,6 +49,7 @@ import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvi
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
||||
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@@ -96,15 +97,15 @@ public class ErrorMvcAutoConfiguration {
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
|
||||
private final WebMvcProperties webMvcProperties;
|
||||
private final DispatcherServletPath dispatcherServletPath;
|
||||
|
||||
private final List<ErrorViewResolver> errorViewResolvers;
|
||||
|
||||
public ErrorMvcAutoConfiguration(ServerProperties serverProperties,
|
||||
WebMvcProperties webMvcProperties,
|
||||
DispatcherServletPath dispatcherServletPath,
|
||||
ObjectProvider<List<ErrorViewResolver>> errorViewResolversProvider) {
|
||||
this.serverProperties = serverProperties;
|
||||
this.webMvcProperties = webMvcProperties;
|
||||
this.dispatcherServletPath = dispatcherServletPath;
|
||||
this.errorViewResolvers = errorViewResolversProvider.getIfAvailable();
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ public class ErrorMvcAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public ErrorPageCustomizer errorPageCustomizer() {
|
||||
return new ErrorPageCustomizer(this.serverProperties, this.webMvcProperties);
|
||||
return new ErrorPageCustomizer(this.serverProperties, this.dispatcherServletPath);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -331,21 +332,20 @@ public class ErrorMvcAutoConfiguration {
|
||||
*/
|
||||
private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
private final ServerProperties properties;
|
||||
|
||||
private final WebMvcProperties webMvcProperties;
|
||||
private final DispatcherServletPath dispatcherServletPath;
|
||||
|
||||
protected ErrorPageCustomizer(ServerProperties serverProperties,
|
||||
WebMvcProperties webMvcProperties) {
|
||||
this.serverProperties = serverProperties;
|
||||
this.webMvcProperties = webMvcProperties;
|
||||
protected ErrorPageCustomizer(ServerProperties properties,
|
||||
DispatcherServletPath dispatcherServletPath) {
|
||||
this.properties = properties;
|
||||
this.dispatcherServletPath = dispatcherServletPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
|
||||
ErrorPage errorPage = new ErrorPage(
|
||||
this.webMvcProperties.getServlet().getServletPrefix()
|
||||
+ this.serverProperties.getError().getPath());
|
||||
ErrorPage errorPage = new ErrorPage(this.dispatcherServletPath
|
||||
.getRelativePath(this.properties.getError().getPath()));
|
||||
errorPageRegistry.addErrorPages(errorPage);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.autoconfigure.security.StaticResourceLocation;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
@@ -74,11 +74,9 @@ public class StaticResourceRequestTests {
|
||||
|
||||
@Test
|
||||
public void atLocationWhenHasServletPathShouldMatchLocation() {
|
||||
WebMvcProperties webMvcProperties = new WebMvcProperties();
|
||||
webMvcProperties.getServlet().setPath("/foo");
|
||||
RequestMatcher matcher = this.resourceRequest.at(StaticResourceLocation.CSS);
|
||||
assertMatcher(matcher, webMvcProperties).matches("/foo", "/css/file.css");
|
||||
assertMatcher(matcher, webMvcProperties).doesNotMatch("/foo", "/js/file.js");
|
||||
assertMatcher(matcher, "/foo").matches("/foo", "/css/file.css");
|
||||
assertMatcher(matcher, "/foo").doesNotMatch("/foo", "/js/file.js");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,15 +94,16 @@ public class StaticResourceRequestTests {
|
||||
}
|
||||
|
||||
private RequestMatcherAssert assertMatcher(RequestMatcher matcher) {
|
||||
DispatcherServletPath dispatcherServletPath = () -> "";
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
context.registerBean(WebMvcProperties.class);
|
||||
context.registerBean(DispatcherServletPath.class, () -> dispatcherServletPath);
|
||||
return assertThat(new RequestMatcherAssert(context, matcher));
|
||||
}
|
||||
|
||||
private RequestMatcherAssert assertMatcher(RequestMatcher matcher,
|
||||
WebMvcProperties webMvcProperties) {
|
||||
private RequestMatcherAssert assertMatcher(RequestMatcher matcher, String path) {
|
||||
DispatcherServletPath dispatcherServletPath = () -> path;
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
context.registerBean(WebMvcProperties.class, () -> webMvcProperties);
|
||||
context.registerBean(DispatcherServletPath.class, () -> dispatcherServletPath);
|
||||
return assertThat(new RequestMatcherAssert(context, matcher));
|
||||
}
|
||||
|
||||
|
||||
@@ -66,8 +66,7 @@ public class DispatcherServletAutoConfigurationTests {
|
||||
.run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(ServletRegistrationBean.class);
|
||||
assertThat(context).doesNotHaveBean(DispatcherServlet.class);
|
||||
assertThat(context)
|
||||
.doesNotHaveBean(DispatcherServletPathProvider.class);
|
||||
assertThat(context).doesNotHaveBean(DispatcherServletPath.class);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -77,7 +76,7 @@ public class DispatcherServletAutoConfigurationTests {
|
||||
public void registrationOverrideWithDispatcherServletWrongName() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomDispatcherServletDifferentName.class,
|
||||
CustomDispatcherServletPathProvider.class)
|
||||
CustomDispatcherServletPath.class)
|
||||
.run((context) -> {
|
||||
ServletRegistrationBean<?> registration = context
|
||||
.getBean(ServletRegistrationBean.class);
|
||||
@@ -91,7 +90,7 @@ public class DispatcherServletAutoConfigurationTests {
|
||||
@Test
|
||||
public void registrationOverrideWithAutowiredServlet() {
|
||||
this.contextRunner.withUserConfiguration(CustomAutowiredRegistration.class,
|
||||
CustomDispatcherServletPathProvider.class).run((context) -> {
|
||||
CustomDispatcherServletPath.class).run((context) -> {
|
||||
ServletRegistrationBean<?> registration = context
|
||||
.getBean(ServletRegistrationBean.class);
|
||||
assertThat(registration.getUrlMappings()).containsExactly("/foo");
|
||||
@@ -111,43 +110,35 @@ public class DispatcherServletAutoConfigurationTests {
|
||||
assertThat(registration.getUrlMappings())
|
||||
.containsExactly("/spring/*");
|
||||
assertThat(registration.getMultipartConfig()).isNull();
|
||||
assertThat(context.getBean(DispatcherServletPathProvider.class)
|
||||
.getServletPaths()).containsExactly("/spring");
|
||||
assertThat(context.getBean(DispatcherServletPath.class).getPath())
|
||||
.isEqualTo("/spring");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathProviderNotCreatedWhenMultipleDispatcherServletsPresent() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomDispatcherServletDifferentName.class)
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(DispatcherServletPathProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathProviderWhenCustomDispatcherServletSameNameShouldReturnConfiguredServletPath() {
|
||||
public void dispatcherServletPathWhenCustomDispatcherServletSameNameShouldReturnConfiguredServletPath() {
|
||||
this.contextRunner.withUserConfiguration(CustomDispatcherServletSameName.class)
|
||||
.withPropertyValues("spring.mvc.servlet.path:/spring")
|
||||
.run((context) -> assertThat(context
|
||||
.getBean(DispatcherServletPathProvider.class).getServletPaths())
|
||||
.containsExactly("/spring"));
|
||||
.run((context) -> assertThat(
|
||||
context.getBean(DispatcherServletPath.class).getPath())
|
||||
.isEqualTo("/spring"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathProviderNotCreatedWhenDefaultDispatcherServletNotAvailable() {
|
||||
public void dispatcherServletPathNotCreatedWhenDefaultDispatcherServletNotAvailable() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomDispatcherServletDifferentName.class,
|
||||
NonServletConfiguration.class)
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(DispatcherServletPathProvider.class));
|
||||
.doesNotHaveBean(DispatcherServletPath.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathProviderNotCreatedWhenCustomRegistrationBeanPresent() {
|
||||
public void dispatcherServletPathNotCreatedWhenCustomRegistrationBeanPresent() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomDispatcherServletRegistration.class)
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(DispatcherServletPathProvider.class));
|
||||
.doesNotHaveBean(DispatcherServletPath.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -237,11 +228,11 @@ public class DispatcherServletAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class CustomDispatcherServletPathProvider {
|
||||
protected static class CustomDispatcherServletPath {
|
||||
|
||||
@Bean
|
||||
public DispatcherServletPathProvider dispatcherServletPathProvider() {
|
||||
return mock(DispatcherServletPathProvider.class);
|
||||
public DispatcherServletPath dispatcherServletPath() {
|
||||
return mock(DispatcherServletPath.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -259,8 +250,8 @@ public class DispatcherServletAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DispatcherServletPathProvider dispatcherServletPathProvider() {
|
||||
return mock(DispatcherServletPathProvider.class);
|
||||
public DispatcherServletPath dispatcherServletPath() {
|
||||
return mock(DispatcherServletPath.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.autoconfigure.web.servlet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link DispatcherServletPath}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class DispatcherServletPathTests {
|
||||
|
||||
@Test
|
||||
public void getRelativePathReturnsRelativePath() {
|
||||
assertThat(((DispatcherServletPath) () -> "spring").getRelativePath("boot"))
|
||||
.isEqualTo("spring/boot");
|
||||
assertThat(((DispatcherServletPath) () -> "spring/").getRelativePath("boot"))
|
||||
.isEqualTo("spring/boot");
|
||||
assertThat(((DispatcherServletPath) () -> "spring").getRelativePath("/boot"))
|
||||
.isEqualTo("spring/boot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPrefixWhenHasSimplePathReturnPath() {
|
||||
assertThat(((DispatcherServletPath) () -> "spring").getPrefix())
|
||||
.isEqualTo("spring");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPrefixWhenHasPatternRemovesPattern() {
|
||||
assertThat(((DispatcherServletPath) () -> "spring/*.do").getPrefix())
|
||||
.isEqualTo("spring");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPathWhenPathEndsWithSlashRemovesSlash() {
|
||||
assertThat(((DispatcherServletPath) () -> "spring/").getPrefix())
|
||||
.isEqualTo("spring");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServletUrlMappingWhenPathIsEmptyReturnsSlash() {
|
||||
assertThat(((DispatcherServletPath) () -> "").getServletUrlMapping())
|
||||
.isEqualTo("/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServletUrlMappingWhenPathIsSlashReturnsSlash() {
|
||||
assertThat(((DispatcherServletPath) () -> "/").getServletUrlMapping())
|
||||
.isEqualTo("/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServletUrlMappingWhenPathContainsStarReturnsPath() {
|
||||
assertThat(((DispatcherServletPath) () -> "spring/*.do").getServletUrlMapping())
|
||||
.isEqualTo("spring/*.do");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServletUrlMappingWhenHasPathNotEndingSlashReturnsSlashStarPattern() {
|
||||
assertThat(((DispatcherServletPath) () -> "spring/boot").getServletUrlMapping())
|
||||
.isEqualTo("spring/boot/*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServletUrlMappingWhenHasPathEndingWithSlashReturnsSlashStarPattern() {
|
||||
assertThat(((DispatcherServletPath) () -> "spring/boot/").getServletUrlMapping())
|
||||
.isEqualTo("spring/boot/*");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.autoconfigure.web.servlet;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link DispatcherServletRegistrationBean}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class DispatcherServletRegistrationBeanTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void createWhenPathIsNullThrowsException() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Path must not be null");
|
||||
new DispatcherServletRegistrationBean(new DispatcherServlet(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPathReturnsPath() {
|
||||
DispatcherServletRegistrationBean bean = new DispatcherServletRegistrationBean(
|
||||
new DispatcherServlet(), "/test");
|
||||
assertThat(bean.getPath()).isEqualTo("/test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrlMappingsReturnsSinglePathMappedPattern() {
|
||||
DispatcherServletRegistrationBean bean = new DispatcherServletRegistrationBean(
|
||||
new DispatcherServlet(), "/test");
|
||||
assertThat(bean.getUrlMappings()).containsOnly("/test/*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setUrlMappingsCannotBeCalled() {
|
||||
DispatcherServletRegistrationBean bean = new DispatcherServletRegistrationBean(
|
||||
new DispatcherServlet(), "/test");
|
||||
this.thrown.expect(UnsupportedOperationException.class);
|
||||
bean.setUrlMappings(Collections.emptyList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addUrlMappingsCannotBeCalled() {
|
||||
DispatcherServletRegistrationBean bean = new DispatcherServletRegistrationBean(
|
||||
new DispatcherServlet(), "/test");
|
||||
this.thrown.expect(UnsupportedOperationException.class);
|
||||
bean.addUrlMappings("/test");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.test.rule.OutputCapture;
|
||||
import org.springframework.boot.web.servlet.error.ErrorAttributes;
|
||||
@@ -39,7 +40,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class ErrorMvcAutoConfigurationTests {
|
||||
|
||||
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ErrorMvcAutoConfiguration.class));
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(DispatcherServletAutoConfiguration.class,
|
||||
ErrorMvcAutoConfiguration.class));
|
||||
|
||||
@Rule
|
||||
public OutputCapture outputCapture = new OutputCapture();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@@ -22,6 +22,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@@ -48,7 +50,7 @@ import org.springframework.web.servlet.DispatcherServlet;
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
|
||||
@EnableConfigurationProperties(WebMvcProperties.class)
|
||||
@EnableConfigurationProperties({ ServerProperties.class, WebMvcProperties.class })
|
||||
public class MockMvcAutoConfiguration {
|
||||
|
||||
private final WebApplicationContext context;
|
||||
@@ -61,6 +63,12 @@ public class MockMvcAutoConfiguration {
|
||||
this.webMvcProperties = webMvcProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DispatcherServletPath dispatcherServletPath() {
|
||||
return () -> this.webMvcProperties.getServlet().getPath();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MockMvcBuilder.class)
|
||||
public DefaultMockMvcBuilder mockMvcBuilder(
|
||||
|
||||
Reference in New Issue
Block a user