Allow template lookup caching to be disabled
Extract TemplateAvailabilityProvider caching logic to a new TemplateAvailabilityProviders class and provide property support to disable it. Also update DevToolsPropertyDefaultsPostProcessor to automatically set the property. Fixes gh-5989
This commit is contained in:
parent
14c7a1284e
commit
ccdcad757a
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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.template;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Collection of {@link TemplateAvailabilityProvider} beans that can be used to check
|
||||
* which (if any) templating engine supports a given view. Caches responses unless the
|
||||
* {@code spring.template.provider.cache} property is set to {@code false}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class TemplateAvailabilityProviders {
|
||||
|
||||
private final List<TemplateAvailabilityProvider> providers;
|
||||
|
||||
private static final int CACHE_LIMIT = 1024;
|
||||
|
||||
private static final TemplateAvailabilityProvider NONE = new NoTemplateAvailabilityProvider();
|
||||
|
||||
/**
|
||||
* resolved template views, returning already cached instances without a global lock.
|
||||
*/
|
||||
private final Map<String, TemplateAvailabilityProvider> resolved = new ConcurrentHashMap<String, TemplateAvailabilityProvider>(
|
||||
CACHE_LIMIT);
|
||||
|
||||
/**
|
||||
* Map from view name resolve template view, synchronized when accessed.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private final Map<String, TemplateAvailabilityProvider> cache = new LinkedHashMap<String, TemplateAvailabilityProvider>(
|
||||
CACHE_LIMIT, 0.75f, true) {
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(
|
||||
Map.Entry<String, TemplateAvailabilityProvider> eldest) {
|
||||
if (size() > CACHE_LIMIT) {
|
||||
TemplateAvailabilityProviders.this.resolved.remove(eldest.getKey());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new {@link TemplateAvailabilityProviders} instance.
|
||||
* @param applicationContext the source application context
|
||||
*/
|
||||
public TemplateAvailabilityProviders(ApplicationContext applicationContext) {
|
||||
this(applicationContext == null ? null : applicationContext.getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link TemplateAvailabilityProviders} instance.
|
||||
* @param classLoader the source class loader
|
||||
*/
|
||||
public TemplateAvailabilityProviders(ClassLoader classLoader) {
|
||||
Assert.notNull(classLoader, "ClassLoader must not be null");
|
||||
this.providers = SpringFactoriesLoader
|
||||
.loadFactories(TemplateAvailabilityProvider.class, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link TemplateAvailabilityProviders} instance.
|
||||
* @param providers the underlying providers
|
||||
*/
|
||||
protected TemplateAvailabilityProviders(
|
||||
Collection<? extends TemplateAvailabilityProvider> providers) {
|
||||
Assert.notNull(providers, "Providers must not be null");
|
||||
this.providers = new ArrayList<TemplateAvailabilityProvider>(providers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying providers being used.
|
||||
* @return the providers being used
|
||||
*/
|
||||
public List<TemplateAvailabilityProvider> getProviders() {
|
||||
return this.providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the provider that can be used to render the given view.
|
||||
* @param view the view to render
|
||||
* @param applicationContext the application context
|
||||
* @return a {@link TemplateAvailabilityProvider} or null
|
||||
*/
|
||||
public TemplateAvailabilityProvider getProvider(String view,
|
||||
ApplicationContext applicationContext) {
|
||||
Assert.notNull(applicationContext, "ApplicationContext must not be null");
|
||||
return getProvider(view, applicationContext.getEnvironment(),
|
||||
applicationContext.getClassLoader(), applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the provider that can be used to render the given view.
|
||||
* @param view the view to render
|
||||
* @param environment the environment
|
||||
* @param classLoader the class loader
|
||||
* @param resourceLoader the resource loader
|
||||
* @return a {@link TemplateAvailabilityProvider} or null
|
||||
*/
|
||||
public TemplateAvailabilityProvider getProvider(String view, Environment environment,
|
||||
ClassLoader classLoader, ResourceLoader resourceLoader) {
|
||||
Assert.notNull(view, "View must not be null");
|
||||
Assert.notNull(environment, "Environment must not be null");
|
||||
Assert.notNull(classLoader, "ClassLoader must not be null");
|
||||
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
|
||||
|
||||
RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(
|
||||
environment, "spring.template.provider.");
|
||||
if (!propertyResolver.getProperty("cache", Boolean.class, true)) {
|
||||
return findProvider(view, environment, classLoader, resourceLoader);
|
||||
}
|
||||
TemplateAvailabilityProvider provider = this.resolved.get(view);
|
||||
if (provider == null) {
|
||||
synchronized (this.cache) {
|
||||
provider = findProvider(view, environment, classLoader, resourceLoader);
|
||||
provider = (provider == null ? NONE : provider);
|
||||
this.resolved.put(view, provider);
|
||||
this.cache.put(view, provider);
|
||||
}
|
||||
}
|
||||
return (provider == NONE ? null : provider);
|
||||
}
|
||||
|
||||
private TemplateAvailabilityProvider findProvider(String view,
|
||||
Environment environment, ClassLoader classLoader,
|
||||
ResourceLoader resourceLoader) {
|
||||
for (TemplateAvailabilityProvider candidate : this.providers) {
|
||||
if (candidate.isTemplateAvailable(view, environment, classLoader,
|
||||
resourceLoader)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class NoTemplateAvailabilityProvider
|
||||
implements TemplateAvailabilityProvider {
|
||||
|
||||
@Override
|
||||
public boolean isTemplateAvailable(String view, Environment environment,
|
||||
ClassLoader classLoader, ResourceLoader resourceLoader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -18,17 +18,17 @@ package org.springframework.boot.autoconfigure.web;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatus.Series;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -70,7 +70,7 @@ public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
|
|||
|
||||
private final ResourceProperties resourceProperties;
|
||||
|
||||
private final List<TemplateAvailabilityProvider> templateAvailabilityProviders;
|
||||
private final TemplateAvailabilityProviders templateAvailabilityProviders;
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
|
@ -81,19 +81,17 @@ public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
|
|||
*/
|
||||
public DefaultErrorViewResolver(ApplicationContext applicationContext,
|
||||
ResourceProperties resourceProperties) {
|
||||
this(applicationContext, resourceProperties,
|
||||
loadTemplateAvailabilityProviders(applicationContext));
|
||||
}
|
||||
|
||||
private static List<TemplateAvailabilityProvider> loadTemplateAvailabilityProviders(
|
||||
ApplicationContext applicationContext) {
|
||||
return SpringFactoriesLoader.loadFactories(TemplateAvailabilityProvider.class,
|
||||
applicationContext == null ? null : applicationContext.getClassLoader());
|
||||
Assert.notNull(applicationContext, "ApplicationContext must not be null");
|
||||
Assert.notNull(resourceProperties, "ResourceProperties must not be null");
|
||||
this.applicationContext = applicationContext;
|
||||
this.resourceProperties = resourceProperties;
|
||||
this.templateAvailabilityProviders = new TemplateAvailabilityProviders(
|
||||
applicationContext);
|
||||
}
|
||||
|
||||
DefaultErrorViewResolver(ApplicationContext applicationContext,
|
||||
ResourceProperties resourceProperties,
|
||||
List<TemplateAvailabilityProvider> templateAvailabilityProviders) {
|
||||
TemplateAvailabilityProviders templateAvailabilityProviders) {
|
||||
Assert.notNull(applicationContext, "ApplicationContext must not be null");
|
||||
Assert.notNull(resourceProperties, "ResourceProperties must not be null");
|
||||
this.applicationContext = applicationContext;
|
||||
|
@ -101,6 +99,14 @@ public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
|
|||
this.templateAvailabilityProviders = templateAvailabilityProviders;
|
||||
}
|
||||
|
||||
DefaultErrorViewResolver(AnnotationConfigApplicationContext applicationContext,
|
||||
ResourceProperties resourceProperties,
|
||||
TemplateAvailabilityProviders templateAvailabilityProviders) {
|
||||
this.applicationContext = applicationContext;
|
||||
this.resourceProperties = resourceProperties;
|
||||
this.templateAvailabilityProviders = templateAvailabilityProviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status,
|
||||
Map<String, Object> model) {
|
||||
|
@ -112,29 +118,20 @@ public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
|
|||
}
|
||||
|
||||
private ModelAndView resolve(String viewName, Map<String, Object> model) {
|
||||
ModelAndView modelAndView = resolveTemplate(viewName, model);
|
||||
if (modelAndView == null) {
|
||||
modelAndView = resolveResource(viewName, model);
|
||||
String errorViewName = "error/" + viewName;
|
||||
TemplateAvailabilityProvider provider = this.templateAvailabilityProviders
|
||||
.getProvider(errorViewName, this.applicationContext);
|
||||
if (provider != null) {
|
||||
return new ModelAndView(errorViewName, model);
|
||||
}
|
||||
return modelAndView;
|
||||
}
|
||||
|
||||
private ModelAndView resolveTemplate(String viewName, Map<String, Object> model) {
|
||||
for (TemplateAvailabilityProvider templateAvailabilityProvider : this.templateAvailabilityProviders) {
|
||||
if (templateAvailabilityProvider.isTemplateAvailable("error/" + viewName,
|
||||
this.applicationContext.getEnvironment(),
|
||||
this.applicationContext.getClassLoader(), this.applicationContext)) {
|
||||
return new ModelAndView("error/" + viewName, model);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return resolveResource(errorViewName, model);
|
||||
}
|
||||
|
||||
private ModelAndView resolveResource(String viewName, Map<String, Object> model) {
|
||||
for (String location : this.resourceProperties.getStaticLocations()) {
|
||||
try {
|
||||
Resource resource = this.applicationContext.getResource(location);
|
||||
resource = resource.createRelative("error/" + viewName + ".html");
|
||||
resource = resource.createRelative(viewName + ".html");
|
||||
if (resource.exists()) {
|
||||
return new ModelAndView(new HtmlResourceView(resource), model);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
|||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.ErrorPage;
|
||||
|
@ -53,7 +54,6 @@ import org.springframework.context.annotation.Conditional;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
|
@ -166,19 +166,15 @@ public class ErrorMvcAutoConfiguration {
|
|||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
List<TemplateAvailabilityProvider> availabilityProviders = SpringFactoriesLoader
|
||||
.loadFactories(TemplateAvailabilityProvider.class,
|
||||
context.getClassLoader());
|
||||
|
||||
for (TemplateAvailabilityProvider availabilityProvider : availabilityProviders) {
|
||||
if (availabilityProvider.isTemplateAvailable("error",
|
||||
context.getEnvironment(), context.getClassLoader(),
|
||||
context.getResourceLoader())) {
|
||||
return ConditionOutcome.noMatch("Template from "
|
||||
+ availabilityProvider + " found for error view");
|
||||
}
|
||||
TemplateAvailabilityProviders providers = new TemplateAvailabilityProviders(
|
||||
context.getClassLoader());
|
||||
TemplateAvailabilityProvider provider = providers.getProvider("error",
|
||||
context.getEnvironment(), context.getClassLoader(),
|
||||
context.getResourceLoader());
|
||||
if (provider != null) {
|
||||
return ConditionOutcome
|
||||
.noMatch("Template from " + provider + " found for error view");
|
||||
}
|
||||
|
||||
return ConditionOutcome.match("No error template view detected");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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.template;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link TemplateAvailabilityProviders}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class TemplateAvailabilityProvidersTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private TemplateAvailabilityProviders providers;
|
||||
|
||||
@Mock
|
||||
private TemplateAvailabilityProvider provider;
|
||||
|
||||
private String view = "view";
|
||||
|
||||
private ClassLoader classLoader = getClass().getClassLoader();
|
||||
|
||||
private MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Mock
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.providers = new TemplateAvailabilityProviders(
|
||||
Collections.singleton(this.provider));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenApplicationContextIsNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("ClassLoader must not be null");
|
||||
new TemplateAvailabilityProviders((ApplicationContext) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenUsingApplicationContextShouldLoadProviders() throws Exception {
|
||||
ApplicationContext applicationContext = mock(ApplicationContext.class);
|
||||
given(applicationContext.getClassLoader()).willReturn(this.classLoader);
|
||||
TemplateAvailabilityProviders providers = new TemplateAvailabilityProviders(
|
||||
applicationContext);
|
||||
assertThat(providers.getProviders()).isNotEmpty();
|
||||
verify(applicationContext).getClassLoader();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenClassLoaderIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("ClassLoader must not be null");
|
||||
new TemplateAvailabilityProviders((ClassLoader) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenUsingClassLoaderShouldLoadProviders() throws Exception {
|
||||
TemplateAvailabilityProviders providers = new TemplateAvailabilityProviders(
|
||||
this.classLoader);
|
||||
assertThat(providers.getProviders()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenProvidersIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Providers must not be null");
|
||||
new TemplateAvailabilityProviders(
|
||||
(Collection<TemplateAvailabilityProvider>) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenUsingProvidersShouldUseProviders() throws Exception {
|
||||
TemplateAvailabilityProviders providers = new TemplateAvailabilityProviders(
|
||||
Collections.singleton(this.provider));
|
||||
assertThat(providers.getProviders()).containsOnly(this.provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderWhenApplicationContextIsNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("ApplicationContext must not be null");
|
||||
this.providers.getProvider(this.view, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderWhenViewIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("View must not be null");
|
||||
this.providers.getProvider(null, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderWhenEnvironmentIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Environment must not be null");
|
||||
this.providers.getProvider(this.view, null, this.classLoader,
|
||||
this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderWhenClassLoaderIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("ClassLoader must not be null");
|
||||
this.providers.getProvider(this.view, this.environment, null,
|
||||
this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderWhenResourceLoaderIsNullShouldThrowException()
|
||||
throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("ResourceLoader must not be null");
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderWhenNoneMatchShouldReturnNull() throws Exception {
|
||||
TemplateAvailabilityProvider found = this.providers.getProvider(this.view,
|
||||
this.environment, this.classLoader, this.resourceLoader);
|
||||
assertThat(found).isNull();
|
||||
verify(this.provider).isTemplateAvailable(this.view, this.environment,
|
||||
this.classLoader, this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderWhenMatchShouldReturnProvider() throws Exception {
|
||||
given(this.provider.isTemplateAvailable(this.view, this.environment,
|
||||
this.classLoader, this.resourceLoader)).willReturn(true);
|
||||
TemplateAvailabilityProvider found = this.providers.getProvider(this.view,
|
||||
this.environment, this.classLoader, this.resourceLoader);
|
||||
assertThat(found).isSameAs(this.provider);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderShouldCacheMatchResult() throws Exception {
|
||||
given(this.provider.isTemplateAvailable(this.view, this.environment,
|
||||
this.classLoader, this.resourceLoader)).willReturn(true);
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
verify(this.provider, times(1)).isTemplateAvailable(this.view, this.environment,
|
||||
this.classLoader, this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProviderShouldCacheNoMatchResult() throws Exception {
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
verify(this.provider, times(1)).isTemplateAvailable(this.view, this.environment,
|
||||
this.classLoader, this.resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProvderWhenCacheDisabledShouldNotUseCache() throws Exception {
|
||||
given(this.provider.isTemplateAvailable(this.view, this.environment,
|
||||
this.classLoader, this.resourceLoader)).willReturn(true);
|
||||
this.environment.setProperty("spring.template.provider.cache", "false");
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
this.providers.getProvider(this.view, this.environment, this.classLoader,
|
||||
this.resourceLoader);
|
||||
verify(this.provider, times(2)).isTemplateAvailable(this.view, this.environment,
|
||||
this.classLoader, this.resourceLoader);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,6 @@ package org.springframework.boot.autoconfigure.web;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -31,6 +30,7 @@ import org.mockito.Mock;
|
|||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.Ordered;
|
||||
|
@ -78,8 +78,8 @@ public class DefaultErrorViewResolverTests {
|
|||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
applicationContext.refresh();
|
||||
this.resourceProperties = new ResourceProperties();
|
||||
List<TemplateAvailabilityProvider> templateAvailabilityProviders = Collections
|
||||
.singletonList(this.templateAvailabilityProvider);
|
||||
TemplateAvailabilityProviders templateAvailabilityProviders = new TestTemplateAvailabilityProviders(
|
||||
this.templateAvailabilityProvider);
|
||||
this.resolver = new DefaultErrorViewResolver(applicationContext,
|
||||
this.resourceProperties, templateAvailabilityProviders);
|
||||
}
|
||||
|
@ -221,4 +221,13 @@ public class DefaultErrorViewResolverTests {
|
|||
return response;
|
||||
}
|
||||
|
||||
private static class TestTemplateAvailabilityProviders
|
||||
extends TemplateAvailabilityProviders {
|
||||
|
||||
TestTemplateAvailabilityProviders(TemplateAvailabilityProvider provider) {
|
||||
super(Collections.singletonList(provider));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro
|
|||
properties.put("server.session.persistent", "true");
|
||||
properties.put("spring.h2.console.enabled", "true");
|
||||
properties.put("spring.resources.cache-period", "0");
|
||||
properties.put("spring.template.provider.cache", "false");
|
||||
PROPERTIES = Collections.unmodifiableMap(properties);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue