Support path discovery for main dispatcher servlet
Add an `DispatcherServletPath` interface which provides a much more
consistent way to discover the path of the main dispatcher servet.
Prior to this commit, auto-configurations would often make use of the
`ServerProperties` class to discover the dispatcher servlet path. This
mechanism isn't very explicit and also makes it hard for us to relocate
that property in Spring Boot 2.1.
This commit also reverts most of fddc9e9c7e
since it is now clear that
the supporting multiple dispatcher servlet paths will be much more
involved that we originally anticipated.
Closes gh-13834
pull/14003/head
parent
d37e717500
commit
9a9111af21
@ -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() + "/*";
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue