Add FreeMarker support
This commit adds auto-configuration and a starter, spring-boot-starter-freemarker, for using FreeMarker view templates in a web application. A new abstraction, TemplateAvailabilityProvider, has been introduced. This decouples ErrorMvcAutoConfiguration from the various view technologies that Spring Boot now supports, allowing it to determine when a custom error template is provided without knowing the details of each view technology. Closes #679
This commit is contained in:
parent
1143f6dbb1
commit
7c91176186
|
|
@ -66,6 +66,11 @@
|
||||||
<artifactId>jetty-webapp</artifactId>
|
<artifactId>jetty-webapp</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.freemarker</groupId>
|
||||||
|
<artifactId>freemarker</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate</groupId>
|
<groupId>org.hibernate</groupId>
|
||||||
<artifactId>hibernate-entitymanager</artifactId>
|
<artifactId>hibernate-entitymanager</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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.freemarker;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.servlet.Servlet;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||||
|
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||||
|
import org.springframework.context.EnvironmentAware;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
||||||
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link EnableAutoConfiguration Auto-configuration} for FreeMarker.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass(freemarker.template.Configuration.class)
|
||||||
|
@ConditionalOnWebApplication
|
||||||
|
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
|
||||||
|
public class FreeMarkerAutoConfiguration {
|
||||||
|
|
||||||
|
public static final String DEFAULT_TEMPLATE_LOADER_PATH = "classpath:/templates/";
|
||||||
|
|
||||||
|
public static final String DEFAULT_PREFIX = "";
|
||||||
|
|
||||||
|
public static final String DEFAULT_SUFFIX = ".ftl";
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public static class FreemarkerConfigurerConfiguration implements EnvironmentAware {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
|
|
||||||
|
private RelaxedPropertyResolver environment;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnvironment(Environment environment) {
|
||||||
|
this.environment = new RelaxedPropertyResolver(environment,
|
||||||
|
"spring.freeMarker.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void checkTemplateLocationExists() {
|
||||||
|
Boolean checkTemplateLocation = this.environment.getProperty(
|
||||||
|
"checkTemplateLocation", Boolean.class, true);
|
||||||
|
if (checkTemplateLocation) {
|
||||||
|
Resource resource = this.resourceLoader.getResource(this.environment
|
||||||
|
.getProperty("templateLoaderPath", DEFAULT_TEMPLATE_LOADER_PATH));
|
||||||
|
Assert.state(resource.exists(), "Cannot find template location: "
|
||||||
|
+ resource + " (please add some templates "
|
||||||
|
+ "or check your FreeMarker configuration)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(name = "freeMarkerConfigurer")
|
||||||
|
public FreeMarkerConfigurer freeMarkerConfigurer() {
|
||||||
|
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
|
||||||
|
freeMarkerConfigurer.setTemplateLoaderPath(this.environment.getProperty(
|
||||||
|
"templateLoaderPath", DEFAULT_TEMPLATE_LOADER_PATH));
|
||||||
|
freeMarkerConfigurer.setDefaultEncoding(this.environment.getProperty(
|
||||||
|
"templateEncoding", "UTF-8"));
|
||||||
|
Map<String, Object> settingsMap = this.environment
|
||||||
|
.getSubProperties("settings.");
|
||||||
|
Properties settings = new Properties();
|
||||||
|
settings.putAll(settingsMap);
|
||||||
|
freeMarkerConfigurer.setFreemarkerSettings(settings);
|
||||||
|
return freeMarkerConfigurer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass(Servlet.class)
|
||||||
|
public static class FreemarkerViewResolverConfiguration implements EnvironmentAware {
|
||||||
|
|
||||||
|
private RelaxedPropertyResolver environment;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnvironment(Environment environment) {
|
||||||
|
this.environment = new RelaxedPropertyResolver(environment,
|
||||||
|
"spring.freeMarker.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(name = "freeMarkerViewResolver")
|
||||||
|
public FreeMarkerViewResolver freeMarkerViewResolver() {
|
||||||
|
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
|
||||||
|
resolver.setPrefix(this.environment.getProperty("prefix", DEFAULT_PREFIX));
|
||||||
|
resolver.setSuffix(this.environment.getProperty("suffix", DEFAULT_SUFFIX));
|
||||||
|
resolver.setCache(this.environment.getProperty("cache", Boolean.class, true));
|
||||||
|
resolver.setContentType(this.environment.getProperty("contentType",
|
||||||
|
"text/html"));
|
||||||
|
resolver.setViewNames(this.environment.getProperty("viewNames",
|
||||||
|
String[].class));
|
||||||
|
resolver.setExposeRequestAttributes(this.environment.getProperty(
|
||||||
|
"exposeRequestAttributes", Boolean.class, false));
|
||||||
|
resolver.setAllowRequestOverride(this.environment.getProperty(
|
||||||
|
"allowRequestOverride", Boolean.class, false));
|
||||||
|
resolver.setExposeSessionAttributes(this.environment.getProperty(
|
||||||
|
"exposeSessionAttributes", Boolean.class, false));
|
||||||
|
resolver.setAllowSessionOverride(this.environment.getProperty(
|
||||||
|
"allowSessionOverride", Boolean.class, false));
|
||||||
|
resolver.setExposeSpringMacroHelpers(this.environment.getProperty(
|
||||||
|
"exposeSpringMacroHelpers", Boolean.class, false));
|
||||||
|
resolver.setRequestContextAttribute(this.environment
|
||||||
|
.getProperty("requestContextAttribute"));
|
||||||
|
|
||||||
|
// This resolver acts as a fallback resolver (e.g. like a
|
||||||
|
// InternalResourceViewResolver) so it needs to have low precedence
|
||||||
|
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
|
||||||
|
|
||||||
|
return resolver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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.freemarker;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.TemplateAvailabilityProvider;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link TemplateAvailabilityProvider} that provides availability information
|
||||||
|
* for FreeMarker view templates
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FreeMarkerTemplateAvailabilityProvider implements
|
||||||
|
TemplateAvailabilityProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTemplateAvailable(String view, Environment environment,
|
||||||
|
ClassLoader classLoader, ResourceLoader resourceLoader) {
|
||||||
|
if (ClassUtils.isPresent("freemarker.template.Configuration",
|
||||||
|
classLoader)) {
|
||||||
|
String loaderPath = environment.getProperty("spring.freemarker.templateLoaderPath",
|
||||||
|
FreeMarkerAutoConfiguration.DEFAULT_TEMPLATE_LOADER_PATH);
|
||||||
|
String prefix = environment.getProperty("spring.freemarker.prefix",
|
||||||
|
FreeMarkerAutoConfiguration.DEFAULT_PREFIX);
|
||||||
|
String suffix = environment.getProperty("spring.freemarker.suffix",
|
||||||
|
FreeMarkerAutoConfiguration.DEFAULT_SUFFIX);
|
||||||
|
return resourceLoader.getResource(loaderPath + prefix + view + suffix).exists();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -52,6 +52,7 @@ import org.thymeleaf.templateresolver.TemplateResolver;
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for Thymeleaf.
|
* {@link EnableAutoConfiguration Auto-configuration} for Thymeleaf.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(SpringTemplateEngine.class)
|
@ConditionalOnClass(SpringTemplateEngine.class)
|
||||||
|
|
@ -108,16 +109,6 @@ public class ThymeleafAutoConfiguration {
|
||||||
protected SpringResourceResourceResolver thymeleafResourceResolver() {
|
protected SpringResourceResourceResolver thymeleafResourceResolver() {
|
||||||
return new SpringResourceResourceResolver();
|
return new SpringResourceResourceResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean templateExists(Environment environment,
|
|
||||||
ResourceLoader resourceLoader, String view) {
|
|
||||||
String prefix = environment.getProperty("spring.thymeleaf.prefix",
|
|
||||||
ThymeleafAutoConfiguration.DEFAULT_PREFIX);
|
|
||||||
String suffix = environment.getProperty("spring.thymeleaf.suffix",
|
|
||||||
ThymeleafAutoConfiguration.DEFAULT_SUFFIX);
|
|
||||||
return resourceLoader.getResource(prefix + view + suffix).exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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.thymeleaf;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.TemplateAvailabilityProvider;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link TemplateAvailabilityProvider} that provides availability information for
|
||||||
|
* Thymeleaf view templates
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ThymeleafTemplateAvailabilityProvider implements
|
||||||
|
TemplateAvailabilityProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTemplateAvailable(String view, Environment environment,
|
||||||
|
ClassLoader classLoader, ResourceLoader resourceLoader) {
|
||||||
|
if (ClassUtils.isPresent("org.thymeleaf.spring4.SpringTemplateEngine",
|
||||||
|
classLoader)) {
|
||||||
|
String prefix = environment.getProperty("spring.thymeleaf.prefix",
|
||||||
|
ThymeleafAutoConfiguration.DEFAULT_PREFIX);
|
||||||
|
String suffix = environment.getProperty("spring.thymeleaf.suffix",
|
||||||
|
ThymeleafAutoConfiguration.DEFAULT_SUFFIX);
|
||||||
|
return resourceLoader.getResource(prefix + view + suffix).exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.boot.autoconfigure.web;
|
package org.springframework.boot.autoconfigure.web;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.Servlet;
|
import javax.servlet.Servlet;
|
||||||
|
|
@ -33,21 +34,21 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||||
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration.DefaultTemplateResolverConfiguration;
|
|
||||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||||
import org.springframework.boot.context.embedded.ErrorPage;
|
import org.springframework.boot.context.embedded.ErrorPage;
|
||||||
|
import org.springframework.boot.web.TemplateAvailabilityProvider;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ConditionContext;
|
import org.springframework.context.annotation.ConditionContext;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.expression.MapAccessor;
|
import org.springframework.context.expression.MapAccessor;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.util.PropertyPlaceholderHelper;
|
import org.springframework.util.PropertyPlaceholderHelper;
|
||||||
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
|
|
@ -59,6 +60,7 @@ import org.springframework.web.servlet.view.BeanNameViewResolver;
|
||||||
* controller.
|
* controller.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
|
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
|
||||||
@ConditionalOnWebApplication
|
@ConditionalOnWebApplication
|
||||||
|
|
@ -116,22 +118,20 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom
|
||||||
@Override
|
@Override
|
||||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||||
AnnotatedTypeMetadata metadata) {
|
AnnotatedTypeMetadata metadata) {
|
||||||
if (ClassUtils.isPresent("org.thymeleaf.spring4.SpringTemplateEngine",
|
List<TemplateAvailabilityProvider> availabilityProviders = SpringFactoriesLoader
|
||||||
context.getClassLoader())) {
|
.loadFactories(TemplateAvailabilityProvider.class,
|
||||||
if (DefaultTemplateResolverConfiguration.templateExists(
|
context.getClassLoader());
|
||||||
context.getEnvironment(), context.getResourceLoader(), "error")) {
|
|
||||||
return ConditionOutcome
|
for (TemplateAvailabilityProvider availabilityProvider : availabilityProviders) {
|
||||||
.noMatch("Thymeleaf template found for error view");
|
if (availabilityProvider.isTemplateAvailable("error",
|
||||||
|
context.getEnvironment(), context.getClassLoader(),
|
||||||
|
context.getResourceLoader())) {
|
||||||
|
return ConditionOutcome.noMatch("Template from "
|
||||||
|
+ availabilityProvider + " found for error view");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ClassUtils.isPresent("org.apache.jasper.compiler.JspConfig",
|
|
||||||
context.getClassLoader())) {
|
return ConditionOutcome.match("No error template view detected");
|
||||||
if (WebMvcAutoConfiguration.templateExists(context.getEnvironment(),
|
|
||||||
context.getResourceLoader(), "error")) {
|
|
||||||
return ConditionOutcome.noMatch("JSP template found for error view");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ConditionOutcome.match("no error template view detected");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.TemplateAvailabilityProvider;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
public class JspTemplateAvailabilityProvider implements TemplateAvailabilityProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTemplateAvailable(String view, Environment environment,
|
||||||
|
ClassLoader classLoader, ResourceLoader resourceLoader) {
|
||||||
|
if (ClassUtils.isPresent("org.apache.jasper.compiler.JspConfig", classLoader)) {
|
||||||
|
String prefix = environment.getProperty("spring.view.prefix",
|
||||||
|
WebMvcAutoConfiguration.DEFAULT_PREFIX);
|
||||||
|
String suffix = environment.getProperty("spring.view.suffix",
|
||||||
|
WebMvcAutoConfiguration.DEFAULT_SUFFIX);
|
||||||
|
return resourceLoader.getResource(prefix + view + suffix).exists();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -43,7 +43,6 @@ import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
import org.springframework.core.convert.converter.GenericConverter;
|
||||||
import org.springframework.core.env.Environment;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
@ -75,6 +74,7 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnWebApplication
|
@ConditionalOnWebApplication
|
||||||
|
|
@ -118,15 +118,6 @@ public class WebMvcAutoConfiguration {
|
||||||
return new HiddenHttpMethodFilter();
|
return new HiddenHttpMethodFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean templateExists(Environment environment,
|
|
||||||
ResourceLoader resourceLoader, String view) {
|
|
||||||
String prefix = environment.getProperty("spring.view.prefix",
|
|
||||||
WebMvcAutoConfiguration.DEFAULT_PREFIX);
|
|
||||||
String suffix = environment.getProperty("spring.view.suffix",
|
|
||||||
WebMvcAutoConfiguration.DEFAULT_SUFFIX);
|
|
||||||
return resourceLoader.getResource(prefix + view + suffix).exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defined as a nested config to ensure WebMvcConfigurerAdapter it not read when not
|
// Defined as a nested config to ensure WebMvcConfigurerAdapter it not read when not
|
||||||
// on the classpath
|
// on the classpath
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
|
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration,\
|
org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.data.MongoRepositoriesAutoConfiguration,\
|
org.springframework.boot.autoconfigure.data.MongoRepositoriesAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
|
|
||||||
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
|
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration,\
|
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
|
||||||
|
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
|
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
|
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\
|
org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\
|
||||||
|
|
@ -23,6 +23,7 @@ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration,\
|
org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
|
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
|
||||||
|
org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
|
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
|
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
|
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
|
||||||
|
|
@ -34,3 +35,10 @@ org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguratio
|
||||||
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
|
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
|
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration
|
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration
|
||||||
|
|
||||||
|
# Template availability providers
|
||||||
|
org.springframework.boot.web.TemplateAvailabilityProvider=\
|
||||||
|
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
|
||||||
|
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
|
||||||
|
org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,205 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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.freemarker;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.BeanCreationException;
|
||||||
|
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
import org.springframework.web.servlet.View;
|
||||||
|
import org.springframework.web.servlet.support.RequestContext;
|
||||||
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
||||||
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link FreeMarkerAutoConfiguration}.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class FreeMarkerAutoConfigurationTests {
|
||||||
|
|
||||||
|
private AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void registerServletContext() {
|
||||||
|
MockServletContext servletContext = new MockServletContext();
|
||||||
|
this.context.setServletContext(servletContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void close() {
|
||||||
|
if (this.context != null) {
|
||||||
|
this.context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defaultConfiguration() {
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
|
||||||
|
assertNotNull(this.context.getBean(FreeMarkerViewResolver.class));
|
||||||
|
|
||||||
|
assertNotNull(this.context.getBean(FreeMarkerConfigurer.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = BeanCreationException.class)
|
||||||
|
public void nonExistentTemplateLocation() {
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.freemarker.templateLoaderPath:classpath:/does-not-exist/");
|
||||||
|
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void emptyTemplateLocation() {
|
||||||
|
new File("target/test-classes/templates/empty-directory").mkdir();
|
||||||
|
|
||||||
|
EnvironmentTestUtils
|
||||||
|
.addEnvironment(this.context,
|
||||||
|
"spring.freemarker.templateLoaderPath:classpath:/templates/empty-directory/");
|
||||||
|
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defaultViewResolution() throws Exception {
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
|
||||||
|
MockHttpServletResponse response = render("home");
|
||||||
|
String result = response.getContentAsString();
|
||||||
|
|
||||||
|
assertTrue("Wrong output: " + result, result.contains("home"));
|
||||||
|
assertEquals("text/html", response.getContentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customContentType() throws Exception {
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.freemarker.contentType:application/json");
|
||||||
|
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
|
||||||
|
MockHttpServletResponse response = render("home");
|
||||||
|
String result = response.getContentAsString();
|
||||||
|
|
||||||
|
assertTrue("Wrong output: " + result, result.contains("home"));
|
||||||
|
assertEquals("application/json", response.getContentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customPrefix() throws Exception {
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.freemarker.prefix:prefix/");
|
||||||
|
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
|
||||||
|
MockHttpServletResponse response = render("prefixed");
|
||||||
|
String result = response.getContentAsString();
|
||||||
|
|
||||||
|
assertTrue("Wrong output: " + result, result.contains("prefixed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customSuffix() throws Exception {
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.freemarker.suffix:.freemarker");
|
||||||
|
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
|
||||||
|
MockHttpServletResponse response = render("suffixed");
|
||||||
|
String result = response.getContentAsString();
|
||||||
|
|
||||||
|
assertTrue("Wrong output: " + result, result.contains("suffixed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customTemplateLoaderPath() throws Exception {
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.freemarker.templateLoaderPath:classpath:/custom-templates/");
|
||||||
|
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
|
||||||
|
MockHttpServletResponse response = render("custom");
|
||||||
|
String result = response.getContentAsString();
|
||||||
|
|
||||||
|
assertTrue("Wrong output: " + result, result.contains("custom"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void disableCache() {
|
||||||
|
EnvironmentTestUtils
|
||||||
|
.addEnvironment(this.context, "spring.freemarker.cache:false");
|
||||||
|
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
|
||||||
|
assertEquals(0, this.context.getBean(FreeMarkerViewResolver.class)
|
||||||
|
.getCacheLimit());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Test
|
||||||
|
public void customFreeMarkerSettings() {
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.freemarker.settings.boolean_format:yup,nope");
|
||||||
|
|
||||||
|
this.context.register(FreeMarkerAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
|
||||||
|
assertEquals("yup,nope", this.context.getBean(FreeMarkerConfigurer.class)
|
||||||
|
.getConfiguration().getSetting("boolean_format"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private MockHttpServletResponse render(String viewName) throws Exception {
|
||||||
|
|
||||||
|
View view = this.context.getBean(FreeMarkerViewResolver.class).resolveViewName(
|
||||||
|
viewName, Locale.UK);
|
||||||
|
assertNotNull(view);
|
||||||
|
|
||||||
|
HttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE,
|
||||||
|
this.context);
|
||||||
|
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
|
||||||
|
view.render(null, request, response);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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.freemarker;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.boot.web.TemplateAvailabilityProvider;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link FreeMarkerTemplateAvailabilityProvider}.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class FreeMarkerTemplateAvailabilityProviderTests {
|
||||||
|
|
||||||
|
private final TemplateAvailabilityProvider provider = new FreeMarkerTemplateAvailabilityProvider();
|
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
|
|
||||||
|
private final MockEnvironment environment = new MockEnvironment();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateInDefaultLocation() {
|
||||||
|
assertTrue(this.provider.isTemplateAvailable("home", this.environment, getClass()
|
||||||
|
.getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateThatDoesNotExist() {
|
||||||
|
assertFalse(this.provider.isTemplateAvailable("whatever", this.environment,
|
||||||
|
getClass().getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateWithCustomLoaderPath() {
|
||||||
|
this.environment.setProperty("spring.freemarker.templateLoaderPath",
|
||||||
|
"classpath:/custom-templates/");
|
||||||
|
|
||||||
|
assertTrue(this.provider.isTemplateAvailable("custom", this.environment,
|
||||||
|
getClass().getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateWithCustomPrefix() {
|
||||||
|
this.environment.setProperty("spring.freemarker.prefix", "prefix/");
|
||||||
|
|
||||||
|
assertTrue(this.provider.isTemplateAvailable("prefixed", this.environment,
|
||||||
|
getClass().getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateWithCustomSuffix() {
|
||||||
|
this.environment.setProperty("spring.freemarker.suffix", ".freemarker");
|
||||||
|
|
||||||
|
assertTrue(this.provider.isTemplateAvailable("suffixed", this.environment,
|
||||||
|
getClass().getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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.thymeleaf;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.boot.web.TemplateAvailabilityProvider;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ThymeleafTemplateAvailabilityProvider}.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class ThymeleafTemplateAvailabilityProviderTests {
|
||||||
|
|
||||||
|
private final TemplateAvailabilityProvider provider = new ThymeleafTemplateAvailabilityProvider();
|
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
|
|
||||||
|
private final MockEnvironment environment = new MockEnvironment();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateInDefaultLocation() {
|
||||||
|
assertTrue(this.provider.isTemplateAvailable("home", this.environment, getClass()
|
||||||
|
.getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateThatDoesNotExist() {
|
||||||
|
assertFalse(this.provider.isTemplateAvailable("whatever", this.environment,
|
||||||
|
getClass().getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateWithCustomPrefix() {
|
||||||
|
this.environment.setProperty("spring.thymeleaf.prefix",
|
||||||
|
"classpath:/custom-templates/");
|
||||||
|
|
||||||
|
assertTrue(this.provider.isTemplateAvailable("custom", this.environment,
|
||||||
|
getClass().getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void availabilityOfTemplateWithCustomSuffix() {
|
||||||
|
this.environment.setProperty("spring.thymeleaf.suffix", ".thymeleaf");
|
||||||
|
|
||||||
|
assertTrue(this.provider.isTemplateAvailable("suffixed", this.environment,
|
||||||
|
getClass().getClassLoader(), this.resourceLoader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
custom
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
home
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
prefixed
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
suffixed
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
<commons-dbcp.version>1.4</commons-dbcp.version>
|
<commons-dbcp.version>1.4</commons-dbcp.version>
|
||||||
<commons-pool.version>1.6</commons-pool.version>
|
<commons-pool.version>1.6</commons-pool.version>
|
||||||
<crashub.version>1.3.0-beta14</crashub.version>
|
<crashub.version>1.3.0-beta14</crashub.version>
|
||||||
|
<freemarker.version>2.3.20</freemarker.version>
|
||||||
<gemfire.version>7.0.1</gemfire.version>
|
<gemfire.version>7.0.1</gemfire.version>
|
||||||
<gradle.version>1.6</gradle.version>
|
<gradle.version>1.6</gradle.version>
|
||||||
<groovy.version>2.3.0-rc-2</groovy.version>
|
<groovy.version>2.3.0-rc-2</groovy.version>
|
||||||
|
|
@ -351,6 +352,11 @@
|
||||||
<artifactId>gemfire</artifactId>
|
<artifactId>gemfire</artifactId>
|
||||||
<version>${gemfire.version}</version>
|
<version>${gemfire.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.freemarker</groupId>
|
||||||
|
<artifactId>freemarker</artifactId>
|
||||||
|
<version>${freemarker.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hamcrest</groupId>
|
<groupId>org.hamcrest</groupId>
|
||||||
<artifactId>hamcrest-library</artifactId>
|
<artifactId>hamcrest-library</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,22 @@ content into your application; rather pick only the properties that you need.
|
||||||
spring.thymeleaf.content-type=text/html # ;charset=<encoding> is added
|
spring.thymeleaf.content-type=text/html # ;charset=<encoding> is added
|
||||||
spring.thymeleaf.cache=true # set to false for hot refresh
|
spring.thymeleaf.cache=true # set to false for hot refresh
|
||||||
|
|
||||||
|
# FREEMARKER ({sc-spring-boot-autoconfigure}}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[FreeMarkerAutoConfiguration])
|
||||||
|
spring.freemarker.allowRequestOverride=false
|
||||||
|
spring.freemarker.allowSessionOverride=false
|
||||||
|
spring.freemarker.cache=true
|
||||||
|
spring.freemarker.checkTemplateLocation=true
|
||||||
|
spring.freemarker.contentType=text/html
|
||||||
|
spring.freemarker.exposeRequestAttributes=false
|
||||||
|
spring.freemarker.exposeSessionAttributes=false
|
||||||
|
spring.freemarker.exposeSpringMacroHelpers=false
|
||||||
|
spring.freemarker.prefix=
|
||||||
|
spring.freemarker.requestContextAttribute=
|
||||||
|
spring.freemarker.suffix=
|
||||||
|
spring.freemarker.templateEncoding=UTF-8
|
||||||
|
spring.freemarker.templateLoaderPath=classpath:/templates/
|
||||||
|
spring.freemarker.viewNames=
|
||||||
|
|
||||||
# INTERNATIONALIZATION ({sc-spring-boot-autoconfigure}/MessageSourceAutoConfiguration.{sc-ext}[MessageSourceAutoConfiguration])
|
# INTERNATIONALIZATION ({sc-spring-boot-autoconfigure}/MessageSourceAutoConfiguration.{sc-ext}[MessageSourceAutoConfiguration])
|
||||||
spring.messages.basename=messages
|
spring.messages.basename=messages
|
||||||
spring.messages.encoding=UTF-8
|
spring.messages.encoding=UTF-8
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ The following auto-configuration classes are from the `spring-boot-autoconfigure
|
||||||
|{sc-spring-boot-autoconfigure}/web/EmbeddedServletContainerAutoConfiguration.{sc-ext}[EmbeddedServletContainerAutoConfiguration]
|
|{sc-spring-boot-autoconfigure}/web/EmbeddedServletContainerAutoConfiguration.{sc-ext}[EmbeddedServletContainerAutoConfiguration]
|
||||||
|{dc-spring-boot-autoconfigure}/web/EmbeddedServletContainerAutoConfiguration.{dc-ext}[javadoc]
|
|{dc-spring-boot-autoconfigure}/web/EmbeddedServletContainerAutoConfiguration.{dc-ext}[javadoc]
|
||||||
|
|
||||||
|
|{sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[FreeMarkerAutoConfiguration]
|
||||||
|
|{dc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{dc-ext}[javadoc]
|
||||||
|
|
||||||
|{sc-spring-boot-autoconfigure}/orm/jpa/HibernateJpaAutoConfiguration.{sc-ext}[HibernateJpaAutoConfiguration]
|
|{sc-spring-boot-autoconfigure}/orm/jpa/HibernateJpaAutoConfiguration.{sc-ext}[HibernateJpaAutoConfiguration]
|
||||||
|{dc-spring-boot-autoconfigure}/orm/jpa/HibernateJpaAutoConfiguration.{dc-ext}[javadoc]
|
|{dc-spring-boot-autoconfigure}/orm/jpa/HibernateJpaAutoConfiguration.{dc-ext}[javadoc]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -809,8 +809,16 @@ added.
|
||||||
`spring.thymeleaf.suffix`, defaults ``classpath:/templates/'' and ``.html''
|
`spring.thymeleaf.suffix`, defaults ``classpath:/templates/'' and ``.html''
|
||||||
respectively). It can be overridden by providing a bean of the same name.
|
respectively). It can be overridden by providing a bean of the same name.
|
||||||
|
|
||||||
Checkout {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`WebMvcAutoConfiguration`]
|
* If you use FreeMarker you will also have a `FreeMarkerViewResolver` with id
|
||||||
and {sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[`ThymeleafAutoConfiguration`]
|
``freeMarkerViewResolver''. It looks for resources in a loader path (externalized to
|
||||||
|
`spring.freemarker.templateLoaderPath`, default ``classpath:/templates/'') by
|
||||||
|
surrounding the view name with a prefix and suffix (externalized to `spring.freemarker.prefix`
|
||||||
|
and `spring.freemarker.suffix`, defaults ``'' and ``.ftl'' respectively). It can be overriden
|
||||||
|
by providing a bean of the same name.
|
||||||
|
|
||||||
|
Check out {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`WebMvcAutoConfiguration`],
|
||||||
|
{sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[`ThymeleafAutoConfiguration`], and
|
||||||
|
{sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}['FreeMarkerAutoConfiguration']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1145,11 +1153,11 @@ you encounter a server error (machine clients consuming JSON and other media typ
|
||||||
see a sensible response with the right error code). To switch it off you can set
|
see a sensible response with the right error code). To switch it off you can set
|
||||||
`error.whitelabel.enabled=false`, but normally in addition or alternatively to that you
|
`error.whitelabel.enabled=false`, but normally in addition or alternatively to that you
|
||||||
will want to add your own error page replacing the whitelabel one. If you are using
|
will want to add your own error page replacing the whitelabel one. If you are using
|
||||||
Thymeleaf you can do this by adding an `error.html` template. In general what you need is
|
Thymeleaf or FreeMarker you can do this by adding an `error.html` or `error.ftl` template
|
||||||
a `View` that resolves with a name of `error`, and/or a `@Controller` that handles the
|
respectively. In general what you need is a `View` that resolves with a name of `error`,
|
||||||
`/error` path. Unless you replaced some of the default configuration you should find a
|
and/or a `@Controller` that handles the `/error` path. Unless you replaced some of the
|
||||||
`BeanNameViewResolver` in your `ApplicationContext` so a `@Bean` with id `error` would be
|
default configuration you should find a `BeanNameViewResolver` in your `ApplicationContext`
|
||||||
a simple way of doing that.
|
so a `@Bean` with id `error` would be a simple way of doing that.
|
||||||
Look at {sc-spring-boot-autoconfigure}/web/ErrorMvcAutoConfiguration.{sc-ext}[`ErrorMvcAutoConfiguration`] for more options.
|
Look at {sc-spring-boot-autoconfigure}/web/ErrorMvcAutoConfiguration.{sc-ext}[`ErrorMvcAutoConfiguration`] for more options.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1251,7 +1259,15 @@ tools.
|
||||||
=== Reload Thymeleaf templates without restarting the container
|
=== Reload Thymeleaf templates without restarting the container
|
||||||
If you are using Thymeleaf, then set `spring.thymeleaf.cache` to `false`. See
|
If you are using Thymeleaf, then set `spring.thymeleaf.cache` to `false`. See
|
||||||
{sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[`ThymeleafAutoConfiguration`]
|
{sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[`ThymeleafAutoConfiguration`]
|
||||||
for other template customization options.
|
for other Thymeleaf customization options.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[howto-reload-freemarker-content]]
|
||||||
|
=== Reload FreeMarker templates without restarting the container
|
||||||
|
If you are using FreeMarker, then set `spring.freemarker.cache` to `false`. See
|
||||||
|
{sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[`FreeMarkerAutoConfiguration`]
|
||||||
|
for other FreeMarker customization options.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
= Spring Boot Reference Guide
|
= Spring Boot Reference Guide
|
||||||
Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch;
|
Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson;
|
||||||
:doctype: book
|
:doctype: book
|
||||||
:toc:
|
:toc:
|
||||||
:toclevels: 4
|
:toclevels: 4
|
||||||
|
|
|
||||||
|
|
@ -892,14 +892,16 @@ and it will be silently ignored by most build tools if you generate a jar.
|
||||||
[[boot-features-spring-mvc-template-engines]]
|
[[boot-features-spring-mvc-template-engines]]
|
||||||
==== Template engines
|
==== Template engines
|
||||||
As well as REST web services, you can also use Spring MVC to serve dynamic HTML content.
|
As well as REST web services, you can also use Spring MVC to serve dynamic HTML content.
|
||||||
Spring MVC supports a variety of templating technologies including: velocity, freemarker,
|
Spring MVC supports a variety of templating technologies including: Velocity, FreeMarker,
|
||||||
and JSPs. Many other templating engines also ship their own Spring MVC integrations.
|
and JSPs. Many other templating engines also ship their own Spring MVC integrations.
|
||||||
|
|
||||||
Spring Boot includes auto-configuration support for the Thymeleaf templating engine.
|
Spring Boot includes auto-configuration support for the Thymeleaf and FreeMarker
|
||||||
Thymeleaf is an XML/XHTML/HTML5 template engine that can work both in web and non-web
|
templating engines. Thymeleaf is an XML/XHTML/HTML5 template engine that can work both in
|
||||||
environments. It allows you to create natural templates that can be correctly displayed
|
web and non-web environments. If allows you to create natural templates that can be
|
||||||
by browsers and therefore work also as static prototypes. Thymeleaf templates will be
|
correctly displayed by browsers and therefore work also as static prototypes. Both
|
||||||
picked up automatically from `src/main/resources/templates`.
|
FreeMarker and Thymeleaf templates will be picked up automatically from
|
||||||
|
`src/main/resources/templates`.
|
||||||
|
|
||||||
|
|
||||||
TIP: JSPs should be avoided if possible, there are several
|
TIP: JSPs should be avoided if possible, there are several
|
||||||
<<boot-features-jsp-limitations, known limitations>> when using them with embedded
|
<<boot-features-jsp-limitations, known limitations>> when using them with embedded
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,9 @@ and Hibernate.
|
||||||
|`spring-boot-starter-data-rest`
|
|`spring-boot-starter-data-rest`
|
||||||
|Support for exposing Spring Data repositories over REST via `spring-data-rest-webmvc`.
|
|Support for exposing Spring Data repositories over REST via `spring-data-rest-webmvc`.
|
||||||
|
|
||||||
|
|`spring-boot-starter-freemarker`
|
||||||
|
|Support for the FreeMarker templating engine
|
||||||
|
|
||||||
|`spring-boot-starter-integration`
|
|`spring-boot-starter-integration`
|
||||||
|Support for common `spring-integration` modules.
|
|Support for common `spring-integration` modules.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
<module>spring-boot-sample-tomcat</module>
|
<module>spring-boot-sample-tomcat</module>
|
||||||
<module>spring-boot-sample-tomcat-multi-connectors</module>
|
<module>spring-boot-sample-tomcat-multi-connectors</module>
|
||||||
<module>spring-boot-sample-traditional</module>
|
<module>spring-boot-sample-traditional</module>
|
||||||
|
<module>spring-boot-sample-web-freemarker</module>
|
||||||
<module>spring-boot-sample-web-method-security</module>
|
<module>spring-boot-sample-web-method-security</module>
|
||||||
<module>spring-boot-sample-web-secure</module>
|
<module>spring-boot-sample-web-secure</module>
|
||||||
<module>spring-boot-sample-web-static</module>
|
<module>spring-boot-sample-web-static</module>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-samples</artifactId>
|
||||||
|
<version>1.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>spring-boot-sample-web-freemarker</artifactId>
|
||||||
|
<name>Spring Boot Web FreeMarker Sample</name>
|
||||||
|
<description>Spring Boot Web FreeMarker Sample</description>
|
||||||
|
<url>http://projects.spring.io/spring-boot/</url>
|
||||||
|
<organization>
|
||||||
|
<name>Pivotal Software, Inc.</name>
|
||||||
|
<url>http://www.spring.io</url>
|
||||||
|
</organization>
|
||||||
|
<properties>
|
||||||
|
<main.basedir>${basedir}/../..</main.basedir>
|
||||||
|
<m2eclipse.wtp.contextRoot>/</m2eclipse.wtp.contextRoot>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<useSystemClassLoader>false</useSystemClassLoader>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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 sample.freemarker;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@ComponentScan
|
||||||
|
public class SampleWebFreeMarkerApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
SpringApplication.run(SampleWebFreeMarkerApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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 sample.freemarker;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class WelcomeController {
|
||||||
|
|
||||||
|
@Value("${application.message:Hello World}")
|
||||||
|
private String message = "Hello World";
|
||||||
|
|
||||||
|
@RequestMapping("/")
|
||||||
|
public String welcome(Map<String, Object> model) {
|
||||||
|
model.put("time", new Date());
|
||||||
|
model.put("message", this.message);
|
||||||
|
return "welcome";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
application.message: Hello, Andy
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
Something went wrong: ${status} ${error}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
Date: ${time?date}
|
||||||
|
<br>
|
||||||
|
Time: ${time?time}
|
||||||
|
<br>
|
||||||
|
Message: ${message}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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 sample.freemarker;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.IntegrationTest;
|
||||||
|
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||||
|
import org.springframework.boot.test.TestRestTemplate;
|
||||||
|
import org.springframework.http.HttpEntity;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic integration tests for FreeMarker application.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@SpringApplicationConfiguration(classes = SampleWebFreeMarkerApplication.class)
|
||||||
|
@WebAppConfiguration
|
||||||
|
@IntegrationTest
|
||||||
|
@DirtiesContext
|
||||||
|
public class SampleWebFreeMarkerApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFreeMarkerTemplate() throws Exception {
|
||||||
|
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
|
||||||
|
"http://localhost:8080", String.class);
|
||||||
|
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||||
|
assertTrue("Wrong body:\n" + entity.getBody(),
|
||||||
|
entity.getBody().contains("Hello, Andy"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFreeMarkerErrorTemplate() throws Exception {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
||||||
|
HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
|
||||||
|
|
||||||
|
ResponseEntity<String> responseEntity = new TestRestTemplate().exchange(
|
||||||
|
"http://localhost:8080/does-not-exist", HttpMethod.GET, requestEntity,
|
||||||
|
String.class);
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());
|
||||||
|
assertTrue("Wrong body:\n" + responseEntity.getBody(), responseEntity.getBody()
|
||||||
|
.contains("Something went wrong: 404 Not Found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
<module>spring-boot-starter-data-mongodb</module>
|
<module>spring-boot-starter-data-mongodb</module>
|
||||||
<module>spring-boot-starter-data-neo4j</module>
|
<module>spring-boot-starter-data-neo4j</module>
|
||||||
<module>spring-boot-starter-data-rest</module>
|
<module>spring-boot-starter-data-rest</module>
|
||||||
|
<module>spring-boot-starter-freemarker</module>
|
||||||
<module>spring-boot-starter-integration</module>
|
<module>spring-boot-starter-integration</module>
|
||||||
<module>spring-boot-starter-jdbc</module>
|
<module>spring-boot-starter-jdbc</module>
|
||||||
<module>spring-boot-starter-jetty</module>
|
<module>spring-boot-starter-jetty</module>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starters</artifactId>
|
||||||
|
<version>1.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||||
|
<name>Spring Boot FreeMarker Starter</name>
|
||||||
|
<description>Spring Boot FreeMarker Starter</description>
|
||||||
|
<url>http://projects.spring.io/spring-boot/</url>
|
||||||
|
<organization>
|
||||||
|
<name>Pivotal Software, Inc.</name>
|
||||||
|
<url>http://www.spring.io</url>
|
||||||
|
</organization>
|
||||||
|
<properties>
|
||||||
|
<main.basedir>${basedir}/../..</main.basedir>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.freemarker</groupId>
|
||||||
|
<artifactId>freemarker</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context-support</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
provides: freemarker,spring-context-support
|
||||||
|
|
@ -101,6 +101,11 @@
|
||||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||||
<version>${spring-boot.version}</version>
|
<version>${spring-boot.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-integration</artifactId>
|
<artifactId>spring-boot-starter-integration</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2014 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.web;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code TemplateAvailabilityProvider} indicates the availability of view templates for
|
||||||
|
* a particular templating engine such as FreeMarker or Thymeleaf
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface TemplateAvailabilityProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if a template is available for the given {@code view},
|
||||||
|
* otherwise {@code false} is returned.
|
||||||
|
*/
|
||||||
|
boolean isTemplateAvailable(String view, Environment environment,
|
||||||
|
ClassLoader classLoader, ResourceLoader resourceLoader);
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue