Polish "Auto-configure templated welcome page"
Closes gh-10545
This commit is contained in:
parent
cc855f4462
commit
2b1d1cd317
|
|
@ -48,14 +48,15 @@ final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping {
|
||||||
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
|
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
|
||||||
ApplicationContext applicationContext, Optional<Resource> welcomePage,
|
ApplicationContext applicationContext, Optional<Resource> welcomePage,
|
||||||
String staticPathPattern) {
|
String staticPathPattern) {
|
||||||
if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
|
if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
|
||||||
|
logger.info("Adding welcome page: " + welcomePage.get());
|
||||||
|
setRootViewName("forward:index.html");
|
||||||
|
}
|
||||||
|
else if (welcomeTemplateExists(templateAvailabilityProviders,
|
||||||
|
applicationContext)) {
|
||||||
logger.info("Adding welcome page template: index");
|
logger.info("Adding welcome page template: index");
|
||||||
setRootViewName("index");
|
setRootViewName("index");
|
||||||
}
|
}
|
||||||
else if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
|
|
||||||
logger.info("Adding welcome page: " + welcomePage);
|
|
||||||
setRootViewName("forward:index.html");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean welcomeTemplateExists(
|
private boolean welcomeTemplateExists(
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,21 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.web.servlet;
|
package org.springframework.boot.autoconfigure.web.servlet;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
||||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
@ -32,10 +39,15 @@ import org.springframework.core.io.FileSystemResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import org.springframework.web.servlet.ViewResolver;
|
||||||
|
import org.springframework.web.servlet.view.AbstractView;
|
||||||
|
import org.springframework.web.servlet.view.InternalResourceView;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
|
@ -109,17 +121,55 @@ public class WelcomePageHandlerMappingTests {
|
||||||
.andExpect(status().isNotFound()));
|
.andExpect(status().isNotFound()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handlesRequestForTemplateThatAcceptsTextHtml() {
|
||||||
|
this.contextRunner.withUserConfiguration(TemplateConfiguration.class)
|
||||||
|
.run((context) -> {
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||||
|
mockMvc.perform(get("/").accept(MediaType.TEXT_HTML))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().string("index template"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handlesRequestForTemplateThatAcceptsAll() {
|
||||||
|
this.contextRunner.withUserConfiguration(TemplateConfiguration.class)
|
||||||
|
.run((context) -> {
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||||
|
mockMvc.perform(get("/").accept(MediaType.ALL))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().string("index template"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void prefersAStaticResourceToATemplate() {
|
||||||
|
this.contextRunner.withUserConfiguration(StaticResourceConfiguration.class,
|
||||||
|
TemplateConfiguration.class).run((context) -> {
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||||
|
mockMvc.perform(get("/").accept(MediaType.ALL))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(forwardedUrl("index.html"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class HandlerMappingConfiguration {
|
static class HandlerMappingConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public WelcomePageHandlerMapping handlerMapping(
|
public WelcomePageHandlerMapping handlerMapping(
|
||||||
ApplicationContext applicationContext,
|
ApplicationContext applicationContext,
|
||||||
|
ObjectProvider<TemplateAvailabilityProviders> templateAvailabilityProviders,
|
||||||
ObjectProvider<Resource> staticIndexPage,
|
ObjectProvider<Resource> staticIndexPage,
|
||||||
@Value("${static-path-pattern:/**}") String staticPathPattern) {
|
@Value("${static-path-pattern:/**}") String staticPathPattern) {
|
||||||
return new WelcomePageHandlerMapping(
|
return new WelcomePageHandlerMapping(
|
||||||
|
templateAvailabilityProviders.getIfAvailable(
|
||||||
|
() -> new TemplateAvailabilityProviders(applicationContext)),
|
||||||
|
applicationContext,
|
||||||
Optional.ofNullable(staticIndexPage.getIfAvailable()),
|
Optional.ofNullable(staticIndexPage.getIfAvailable()),
|
||||||
staticPathPattern);
|
staticPathPattern);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -134,4 +184,43 @@ public class WelcomePageHandlerMappingTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class TemplateConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public TemplateAvailabilityProviders templateAvailabilityProviders() {
|
||||||
|
return new TestTemplateAvailabilityProviders((view, environment, classLoader,
|
||||||
|
resourceLoader) -> view.equals("index"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ViewResolver viewResolver() {
|
||||||
|
return (name, locale) -> {
|
||||||
|
if (name.startsWith("forward:")) {
|
||||||
|
return new InternalResourceView(name.substring("forward:".length()));
|
||||||
|
}
|
||||||
|
return new AbstractView() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderMergedOutputModel(Map<String, Object> model,
|
||||||
|
HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws Exception {
|
||||||
|
response.getWriter().print(name + " template");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestTemplateAvailabilityProviders
|
||||||
|
extends TemplateAvailabilityProviders {
|
||||||
|
|
||||||
|
TestTemplateAvailabilityProviders(TemplateAvailabilityProvider provider) {
|
||||||
|
super(Collections.singletonList(provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1952,9 +1952,7 @@ By default, resources are mapped on `+/**+`, but you can tune that with the
|
||||||
You can also customize the static resource locations by using the
|
You can also customize the static resource locations by using the
|
||||||
`spring.resources.static-locations` property (replacing the default values with a list of
|
`spring.resources.static-locations` property (replacing the default values with a list of
|
||||||
directory locations). The root Servlet context path `"/"` is automatically added as a
|
directory locations). The root Servlet context path `"/"` is automatically added as a
|
||||||
location as well. If you do this, the default welcome page detection switches to your
|
location as well.
|
||||||
custom locations. So, if there is an `index.html` in any of your locations on startup, it
|
|
||||||
is the home page of the application.
|
|
||||||
|
|
||||||
In addition to the '`standard`' static resource locations mentioned earlier, a special
|
In addition to the '`standard`' static resource locations mentioned earlier, a special
|
||||||
case is made for http://www.webjars.org/[Webjars content]. Any resources with a path in
|
case is made for http://www.webjars.org/[Webjars content]. Any resources with a path in
|
||||||
|
|
@ -2022,6 +2020,13 @@ post] and in Spring Framework's
|
||||||
{spring-reference}web.html#mvc-config-static-resources[reference documentation].
|
{spring-reference}web.html#mvc-config-static-resources[reference documentation].
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[boot-features-spring-mvc-welcome-page]]
|
||||||
|
==== Welcome Page
|
||||||
|
Spring Boot support both static and templated welcome pages. It first looks for an
|
||||||
|
`index.html` file in the configured static content locations. If one is not found, it
|
||||||
|
then looks for an `index` template. If either is found it is automatically used as the
|
||||||
|
welcome page of the application.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[boot-features-spring-mvc-favicon]]
|
[[boot-features-spring-mvc-favicon]]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue