From 57006ee82eff57efc08d2bc92068a11f4a8e0ced Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 14 Mar 2025 16:10:56 +0000 Subject: [PATCH] Remove web concerns from template package and move out of -all Co-authored-by: Phillip Webb --- .../freemarker/FreeMarkerProperties.java | 239 ++++++++++++++++- .../template/GroovyTemplateProperties.java | 241 +++++++++++++++++- ...bstractTemplateViewResolverProperties.java | 175 ------------- .../AbstractViewResolverProperties.java | 131 ---------- .../resources/META-INF/spring/aot.factories | 3 +- .../FreeMarkerPropertiesTests.java} | 22 +- .../GroovyTemplatePropertiesTests.java | 69 +++++ ...PathBasedTemplateAvailabilityProvider.java | 2 +- .../TemplateAvailabilityProvider.java | 2 +- .../TemplateAvailabilityProviders.java | 0 .../template/TemplateLocation.java | 0 .../template/TemplateRuntimeHints.java | 0 .../autoconfigure/template/package-info.java | 2 +- .../resources/META-INF/spring/aot.factories | 3 + 14 files changed, 556 insertions(+), 333 deletions(-) delete mode 100644 spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/AbstractTemplateViewResolverProperties.java delete mode 100644 spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/AbstractViewResolverProperties.java rename spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/{template/ViewResolverPropertiesTests.java => freemarker/FreeMarkerPropertiesTests.java} (73%) create mode 100644 spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplatePropertiesTests.java rename spring-boot-project/{spring-boot-autoconfigure-all => spring-boot-autoconfigure}/src/main/java/org/springframework/boot/autoconfigure/template/PathBasedTemplateAvailabilityProvider.java (98%) rename spring-boot-project/{spring-boot-autoconfigure-all => spring-boot-autoconfigure}/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvider.java (96%) rename spring-boot-project/{spring-boot-autoconfigure-all => spring-boot-autoconfigure}/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProviders.java (100%) rename spring-boot-project/{spring-boot-autoconfigure-all => spring-boot-autoconfigure}/src/main/java/org/springframework/boot/autoconfigure/template/TemplateLocation.java (100%) rename spring-boot-project/{spring-boot-autoconfigure-all => spring-boot-autoconfigure}/src/main/java/org/springframework/boot/autoconfigure/template/TemplateRuntimeHints.java (100%) rename spring-boot-project/{spring-boot-autoconfigure-all => spring-boot-autoconfigure}/src/main/java/org/springframework/boot/autoconfigure/template/package-info.java (92%) diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerProperties.java b/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerProperties.java index 9b8615719b..c0c9c5576b 100644 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerProperties.java @@ -16,11 +16,17 @@ package org.springframework.boot.autoconfigure.freemarker; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; -import org.springframework.boot.autoconfigure.template.AbstractTemplateViewResolverProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.core.Ordered; +import org.springframework.util.Assert; +import org.springframework.util.MimeType; +import org.springframework.web.servlet.view.AbstractTemplateViewResolver; /** * {@link ConfigurationProperties @ConfigurationProperties} for configuring FreeMarker. @@ -30,7 +36,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @since 1.1.0 */ @ConfigurationProperties("spring.freemarker") -public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties { +public class FreeMarkerProperties { public static final String DEFAULT_TEMPLATE_LOADER_PATH = "classpath:/templates/"; @@ -38,6 +44,85 @@ public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties public static final String DEFAULT_SUFFIX = ".ftlh"; + private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html"); + + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + + /** + * Whether to enable MVC view resolution for this technology. + */ + private boolean enabled = true; + + /** + * Whether to enable template caching. + */ + private boolean cache; + + /** + * Content-Type value. + */ + private MimeType contentType = DEFAULT_CONTENT_TYPE; + + /** + * Template encoding. + */ + private Charset charset = DEFAULT_CHARSET; + + /** + * View names that can be resolved. + */ + private String[] viewNames; + + /** + * Whether to check that the templates location exists. + */ + private boolean checkTemplateLocation = true; + + /** + * Prefix that gets prepended to view names when building a URL. + */ + private String prefix = DEFAULT_PREFIX; + + /** + * Suffix that gets appended to view names when building a URL. + */ + private String suffix = DEFAULT_SUFFIX; + + /** + * Name of the RequestContext attribute for all views. + */ + private String requestContextAttribute; + + /** + * Whether all request attributes should be added to the model prior to merging with + * the template. + */ + private boolean exposeRequestAttributes = false; + + /** + * Whether all HttpSession attributes should be added to the model prior to merging + * with the template. + */ + private boolean exposeSessionAttributes = false; + + /** + * Whether HttpServletRequest attributes are allowed to override (hide) controller + * generated model attributes of the same name. + */ + private boolean allowRequestOverride = false; + + /** + * Whether to expose a RequestContext for use by Spring's macro library, under the + * name "springMacroRequestContext". + */ + private boolean exposeSpringMacroHelpers = true; + + /** + * Whether HttpSession attributes are allowed to override (hide) controller generated + * model attributes of the same name. + */ + private boolean allowSessionOverride = false; + /** * Well-known FreeMarker keys which are passed to FreeMarker's Configuration. */ @@ -56,8 +141,62 @@ public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties */ private boolean preferFileSystemAccess; - public FreeMarkerProperties() { - super(DEFAULT_PREFIX, DEFAULT_SUFFIX); + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isEnabled() { + return this.enabled; + } + + public void setCheckTemplateLocation(boolean checkTemplateLocation) { + this.checkTemplateLocation = checkTemplateLocation; + } + + public boolean isCheckTemplateLocation() { + return this.checkTemplateLocation; + } + + public String[] getViewNames() { + return this.viewNames; + } + + public void setViewNames(String[] viewNames) { + this.viewNames = viewNames; + } + + public boolean isCache() { + return this.cache; + } + + public void setCache(boolean cache) { + this.cache = cache; + } + + public MimeType getContentType() { + if (this.contentType.getCharset() == null) { + Map parameters = new LinkedHashMap<>(); + parameters.put("charset", this.charset.name()); + parameters.putAll(this.contentType.getParameters()); + return new MimeType(this.contentType, parameters); + } + return this.contentType; + } + + public void setContentType(MimeType contentType) { + this.contentType = contentType; + } + + public Charset getCharset() { + return this.charset; + } + + public String getCharsetName() { + return (this.charset != null) ? this.charset.name() : null; + } + + public void setCharset(Charset charset) { + this.charset = charset; } public Map getSettings() { @@ -84,4 +223,96 @@ public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties this.preferFileSystemAccess = preferFileSystemAccess; } + public String getPrefix() { + return this.prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String getSuffix() { + return this.suffix; + } + + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + public String getRequestContextAttribute() { + return this.requestContextAttribute; + } + + public void setRequestContextAttribute(String requestContextAttribute) { + this.requestContextAttribute = requestContextAttribute; + } + + public boolean isExposeRequestAttributes() { + return this.exposeRequestAttributes; + } + + public void setExposeRequestAttributes(boolean exposeRequestAttributes) { + this.exposeRequestAttributes = exposeRequestAttributes; + } + + public boolean isExposeSessionAttributes() { + return this.exposeSessionAttributes; + } + + public void setExposeSessionAttributes(boolean exposeSessionAttributes) { + this.exposeSessionAttributes = exposeSessionAttributes; + } + + public boolean isAllowRequestOverride() { + return this.allowRequestOverride; + } + + public void setAllowRequestOverride(boolean allowRequestOverride) { + this.allowRequestOverride = allowRequestOverride; + } + + public boolean isAllowSessionOverride() { + return this.allowSessionOverride; + } + + public void setAllowSessionOverride(boolean allowSessionOverride) { + this.allowSessionOverride = allowSessionOverride; + } + + public boolean isExposeSpringMacroHelpers() { + return this.exposeSpringMacroHelpers; + } + + public void setExposeSpringMacroHelpers(boolean exposeSpringMacroHelpers) { + this.exposeSpringMacroHelpers = exposeSpringMacroHelpers; + } + + /** + * Apply the given properties to a {@link AbstractTemplateViewResolver}. Use Object in + * signature to avoid runtime dependency on MVC, which means that the template engine + * can be used in a non-web application. + * @param viewResolver the resolver to apply the properties to. + */ + public void applyToMvcViewResolver(Object viewResolver) { + Assert.isInstanceOf(AbstractTemplateViewResolver.class, viewResolver, + () -> "ViewResolver is not an instance of AbstractTemplateViewResolver :" + viewResolver); + AbstractTemplateViewResolver resolver = (AbstractTemplateViewResolver) viewResolver; + resolver.setPrefix(getPrefix()); + resolver.setSuffix(getSuffix()); + resolver.setCache(isCache()); + if (getContentType() != null) { + resolver.setContentType(getContentType().toString()); + } + resolver.setViewNames(getViewNames()); + resolver.setExposeRequestAttributes(isExposeRequestAttributes()); + resolver.setAllowRequestOverride(isAllowRequestOverride()); + resolver.setAllowSessionOverride(isAllowSessionOverride()); + resolver.setExposeSessionAttributes(isExposeSessionAttributes()); + resolver.setExposeSpringMacroHelpers(isExposeSpringMacroHelpers()); + resolver.setRequestContextAttribute(getRequestContextAttribute()); + // The resolver usually acts as a fallback resolver (e.g. like a + // InternalResourceViewResolver) so it needs to have low precedence + resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5); + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateProperties.java b/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateProperties.java index b43497ca41..b407cbbceb 100644 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateProperties.java @@ -16,12 +16,19 @@ package org.springframework.boot.autoconfigure.groovy.template; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.LinkedHashMap; import java.util.Locale; +import java.util.Map; import groovy.text.markup.BaseTemplate; -import org.springframework.boot.autoconfigure.template.AbstractTemplateViewResolverProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.core.Ordered; +import org.springframework.util.Assert; +import org.springframework.util.MimeType; +import org.springframework.web.servlet.view.AbstractTemplateViewResolver; /** * {@link ConfigurationProperties @ConfigurationProperties} for configuring Groovy @@ -32,7 +39,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @since 1.1.0 */ @ConfigurationProperties("spring.groovy.template") -public class GroovyTemplateProperties extends AbstractTemplateViewResolverProperties { +public class GroovyTemplateProperties { public static final String DEFAULT_RESOURCE_LOADER_PATH = "classpath:/templates/"; @@ -42,6 +49,85 @@ public class GroovyTemplateProperties extends AbstractTemplateViewResolverProper public static final String DEFAULT_REQUEST_CONTEXT_ATTRIBUTE = "spring"; + private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html"); + + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + + /** + * Whether to enable MVC view resolution for this technology. + */ + private boolean enabled = true; + + /** + * Whether to enable template caching. + */ + private boolean cache; + + /** + * Content-Type value. + */ + private MimeType contentType = DEFAULT_CONTENT_TYPE; + + /** + * Template encoding. + */ + private Charset charset = DEFAULT_CHARSET; + + /** + * View names that can be resolved. + */ + private String[] viewNames; + + /** + * Whether to check that the templates location exists. + */ + private boolean checkTemplateLocation = true; + + /** + * Prefix that gets prepended to view names when building a URL. + */ + private String prefix = DEFAULT_PREFIX; + + /** + * Suffix that gets appended to view names when building a URL. + */ + private String suffix = DEFAULT_SUFFIX; + + /** + * Name of the RequestContext attribute for all views. + */ + private String requestContextAttribute = DEFAULT_REQUEST_CONTEXT_ATTRIBUTE; + + /** + * Whether all request attributes should be added to the model prior to merging with + * the template. + */ + private boolean exposeRequestAttributes = false; + + /** + * Whether all HttpSession attributes should be added to the model prior to merging + * with the template. + */ + private boolean exposeSessionAttributes = false; + + /** + * Whether HttpServletRequest attributes are allowed to override (hide) controller + * generated model attributes of the same name. + */ + private boolean allowRequestOverride = false; + + /** + * Whether to expose a RequestContext for use by Spring's macro library, under the + * name "springMacroRequestContext". + */ + private boolean exposeSpringMacroHelpers = true; + + /** + * Whether HttpSession attributes are allowed to override (hide) controller generated + * model attributes of the same name. + */ + private boolean allowSessionOverride = false; + /** * Whether models that are assignable to CharSequence are escaped automatically. */ @@ -98,9 +184,62 @@ public class GroovyTemplateProperties extends AbstractTemplateViewResolverProper */ private boolean useDoubleQuotes; - public GroovyTemplateProperties() { - super(DEFAULT_PREFIX, DEFAULT_SUFFIX); - setRequestContextAttribute(DEFAULT_REQUEST_CONTEXT_ATTRIBUTE); + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isCheckTemplateLocation() { + return this.checkTemplateLocation; + } + + public void setCheckTemplateLocation(boolean checkTemplateLocation) { + this.checkTemplateLocation = checkTemplateLocation; + } + + public String[] getViewNames() { + return this.viewNames; + } + + public void setViewNames(String[] viewNames) { + this.viewNames = viewNames; + } + + public boolean isCache() { + return this.cache; + } + + public void setCache(boolean cache) { + this.cache = cache; + } + + public MimeType getContentType() { + if (this.contentType.getCharset() == null) { + Map parameters = new LinkedHashMap<>(); + parameters.put("charset", this.charset.name()); + parameters.putAll(this.contentType.getParameters()); + return new MimeType(this.contentType, parameters); + } + return this.contentType; + } + + public void setContentType(MimeType contentType) { + this.contentType = contentType; + } + + public Charset getCharset() { + return this.charset; + } + + public String getCharsetName() { + return (this.charset != null) ? this.charset.name() : null; + } + + public void setCharset(Charset charset) { + this.charset = charset; } public boolean isAutoEscape() { @@ -191,4 +330,96 @@ public class GroovyTemplateProperties extends AbstractTemplateViewResolverProper this.useDoubleQuotes = useDoubleQuotes; } + public String getPrefix() { + return this.prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String getSuffix() { + return this.suffix; + } + + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + public String getRequestContextAttribute() { + return this.requestContextAttribute; + } + + public void setRequestContextAttribute(String requestContextAttribute) { + this.requestContextAttribute = requestContextAttribute; + } + + public boolean isExposeRequestAttributes() { + return this.exposeRequestAttributes; + } + + public void setExposeRequestAttributes(boolean exposeRequestAttributes) { + this.exposeRequestAttributes = exposeRequestAttributes; + } + + public boolean isExposeSessionAttributes() { + return this.exposeSessionAttributes; + } + + public void setExposeSessionAttributes(boolean exposeSessionAttributes) { + this.exposeSessionAttributes = exposeSessionAttributes; + } + + public boolean isAllowRequestOverride() { + return this.allowRequestOverride; + } + + public void setAllowRequestOverride(boolean allowRequestOverride) { + this.allowRequestOverride = allowRequestOverride; + } + + public boolean isAllowSessionOverride() { + return this.allowSessionOverride; + } + + public void setAllowSessionOverride(boolean allowSessionOverride) { + this.allowSessionOverride = allowSessionOverride; + } + + public boolean isExposeSpringMacroHelpers() { + return this.exposeSpringMacroHelpers; + } + + public void setExposeSpringMacroHelpers(boolean exposeSpringMacroHelpers) { + this.exposeSpringMacroHelpers = exposeSpringMacroHelpers; + } + + /** + * Apply the given properties to a {@link AbstractTemplateViewResolver}. Use Object in + * signature to avoid runtime dependency on MVC, which means that the template engine + * can be used in a non-web application. + * @param viewResolver the resolver to apply the properties to. + */ + public void applyToMvcViewResolver(Object viewResolver) { + Assert.isInstanceOf(AbstractTemplateViewResolver.class, viewResolver, + () -> "ViewResolver is not an instance of AbstractTemplateViewResolver :" + viewResolver); + AbstractTemplateViewResolver resolver = (AbstractTemplateViewResolver) viewResolver; + resolver.setPrefix(getPrefix()); + resolver.setSuffix(getSuffix()); + resolver.setCache(isCache()); + if (getContentType() != null) { + resolver.setContentType(getContentType().toString()); + } + resolver.setViewNames(getViewNames()); + resolver.setExposeRequestAttributes(isExposeRequestAttributes()); + resolver.setAllowRequestOverride(isAllowRequestOverride()); + resolver.setAllowSessionOverride(isAllowSessionOverride()); + resolver.setExposeSessionAttributes(isExposeSessionAttributes()); + resolver.setExposeSpringMacroHelpers(isExposeSpringMacroHelpers()); + resolver.setRequestContextAttribute(getRequestContextAttribute()); + // The resolver usually acts as a fallback resolver (e.g. like a + // InternalResourceViewResolver) so it needs to have low precedence + resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5); + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/AbstractTemplateViewResolverProperties.java b/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/AbstractTemplateViewResolverProperties.java deleted file mode 100644 index b9422a539d..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/AbstractTemplateViewResolverProperties.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2012-2020 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 - * - * https://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 org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.core.Ordered; -import org.springframework.util.Assert; -import org.springframework.web.servlet.view.AbstractTemplateViewResolver; - -/** - * Base class for {@link ConfigurationProperties @ConfigurationProperties} of a - * {@link AbstractTemplateViewResolver}. - * - * @author Andy Wilkinson - * @since 1.1.0 - */ -public abstract class AbstractTemplateViewResolverProperties extends AbstractViewResolverProperties { - - /** - * Prefix that gets prepended to view names when building a URL. - */ - private String prefix; - - /** - * Suffix that gets appended to view names when building a URL. - */ - private String suffix; - - /** - * Name of the RequestContext attribute for all views. - */ - private String requestContextAttribute; - - /** - * Whether all request attributes should be added to the model prior to merging with - * the template. - */ - private boolean exposeRequestAttributes = false; - - /** - * Whether all HttpSession attributes should be added to the model prior to merging - * with the template. - */ - private boolean exposeSessionAttributes = false; - - /** - * Whether HttpServletRequest attributes are allowed to override (hide) controller - * generated model attributes of the same name. - */ - private boolean allowRequestOverride = false; - - /** - * Whether to expose a RequestContext for use by Spring's macro library, under the - * name "springMacroRequestContext". - */ - private boolean exposeSpringMacroHelpers = true; - - /** - * Whether HttpSession attributes are allowed to override (hide) controller generated - * model attributes of the same name. - */ - private boolean allowSessionOverride = false; - - protected AbstractTemplateViewResolverProperties(String defaultPrefix, String defaultSuffix) { - this.prefix = defaultPrefix; - this.suffix = defaultSuffix; - } - - public String getPrefix() { - return this.prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - public String getSuffix() { - return this.suffix; - } - - public void setSuffix(String suffix) { - this.suffix = suffix; - } - - public String getRequestContextAttribute() { - return this.requestContextAttribute; - } - - public void setRequestContextAttribute(String requestContextAttribute) { - this.requestContextAttribute = requestContextAttribute; - } - - public boolean isExposeRequestAttributes() { - return this.exposeRequestAttributes; - } - - public void setExposeRequestAttributes(boolean exposeRequestAttributes) { - this.exposeRequestAttributes = exposeRequestAttributes; - } - - public boolean isExposeSessionAttributes() { - return this.exposeSessionAttributes; - } - - public void setExposeSessionAttributes(boolean exposeSessionAttributes) { - this.exposeSessionAttributes = exposeSessionAttributes; - } - - public boolean isAllowRequestOverride() { - return this.allowRequestOverride; - } - - public void setAllowRequestOverride(boolean allowRequestOverride) { - this.allowRequestOverride = allowRequestOverride; - } - - public boolean isAllowSessionOverride() { - return this.allowSessionOverride; - } - - public void setAllowSessionOverride(boolean allowSessionOverride) { - this.allowSessionOverride = allowSessionOverride; - } - - public boolean isExposeSpringMacroHelpers() { - return this.exposeSpringMacroHelpers; - } - - public void setExposeSpringMacroHelpers(boolean exposeSpringMacroHelpers) { - this.exposeSpringMacroHelpers = exposeSpringMacroHelpers; - } - - /** - * Apply the given properties to a {@link AbstractTemplateViewResolver}. Use Object in - * signature to avoid runtime dependency on MVC, which means that the template engine - * can be used in a non-web application. - * @param viewResolver the resolver to apply the properties to. - */ - public void applyToMvcViewResolver(Object viewResolver) { - Assert.isInstanceOf(AbstractTemplateViewResolver.class, viewResolver, - () -> "ViewResolver is not an instance of AbstractTemplateViewResolver :" + viewResolver); - AbstractTemplateViewResolver resolver = (AbstractTemplateViewResolver) viewResolver; - resolver.setPrefix(getPrefix()); - resolver.setSuffix(getSuffix()); - resolver.setCache(isCache()); - if (getContentType() != null) { - resolver.setContentType(getContentType().toString()); - } - resolver.setViewNames(getViewNames()); - resolver.setExposeRequestAttributes(isExposeRequestAttributes()); - resolver.setAllowRequestOverride(isAllowRequestOverride()); - resolver.setAllowSessionOverride(isAllowSessionOverride()); - resolver.setExposeSessionAttributes(isExposeSessionAttributes()); - resolver.setExposeSpringMacroHelpers(isExposeSpringMacroHelpers()); - resolver.setRequestContextAttribute(getRequestContextAttribute()); - // The resolver usually acts as a fallback resolver (e.g. like a - // InternalResourceViewResolver) so it needs to have low precedence - resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5); - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/AbstractViewResolverProperties.java b/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/AbstractViewResolverProperties.java deleted file mode 100644 index c64f92d0ec..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/AbstractViewResolverProperties.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2012-2020 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 - * - * https://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.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.util.MimeType; -import org.springframework.web.servlet.ViewResolver; - -/** - * Base class for {@link ConfigurationProperties @ConfigurationProperties} of a - * {@link ViewResolver}. - * - * @author Andy Wilkinson - * @author Stephane Nicoll - * @since 1.2.0 - * @see AbstractTemplateViewResolverProperties - */ -public abstract class AbstractViewResolverProperties { - - private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html"); - - private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; - - /** - * Whether to enable MVC view resolution for this technology. - */ - private boolean enabled = true; - - /** - * Whether to enable template caching. - */ - private boolean cache; - - /** - * Content-Type value. - */ - private MimeType contentType = DEFAULT_CONTENT_TYPE; - - /** - * Template encoding. - */ - private Charset charset = DEFAULT_CHARSET; - - /** - * View names that can be resolved. - */ - private String[] viewNames; - - /** - * Whether to check that the templates location exists. - */ - private boolean checkTemplateLocation = true; - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public boolean isEnabled() { - return this.enabled; - } - - public void setCheckTemplateLocation(boolean checkTemplateLocation) { - this.checkTemplateLocation = checkTemplateLocation; - } - - public boolean isCheckTemplateLocation() { - return this.checkTemplateLocation; - } - - public String[] getViewNames() { - return this.viewNames; - } - - public void setViewNames(String[] viewNames) { - this.viewNames = viewNames; - } - - public boolean isCache() { - return this.cache; - } - - public void setCache(boolean cache) { - this.cache = cache; - } - - public MimeType getContentType() { - if (this.contentType.getCharset() == null) { - Map parameters = new LinkedHashMap<>(); - parameters.put("charset", this.charset.name()); - parameters.putAll(this.contentType.getParameters()); - return new MimeType(this.contentType, parameters); - } - return this.contentType; - } - - public void setContentType(MimeType contentType) { - this.contentType = contentType; - } - - public Charset getCharset() { - return this.charset; - } - - public String getCharsetName() { - return (this.charset != null) ? this.charset.name() : null; - } - - public void setCharset(Charset charset) { - this.charset = charset; - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/resources/META-INF/spring/aot.factories b/spring-boot-project/spring-boot-autoconfigure-all/src/main/resources/META-INF/spring/aot.factories index 96e329a44c..b43e9316d1 100644 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/main/resources/META-INF/spring/aot.factories +++ b/spring-boot-project/spring-boot-autoconfigure-all/src/main/resources/META-INF/spring/aot.factories @@ -1,8 +1,7 @@ org.springframework.aot.hint.RuntimeHintsRegistrar=\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider$FreeMarkerTemplateAvailabilityRuntimeHints,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider$GroovyTemplateAvailabilityRuntimeHints,\ -org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonAutoConfigurationRuntimeHints,\ -org.springframework.boot.autoconfigure.template.TemplateRuntimeHints +org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonAutoConfigurationRuntimeHints org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\ org.springframework.boot.autoconfigure.flyway.ResourceProviderCustomizerBeanRegistrationAotProcessor diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/template/ViewResolverPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerPropertiesTests.java similarity index 73% rename from spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/template/ViewResolverPropertiesTests.java rename to spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerPropertiesTests.java index 8e800ad1ff..f93378a0f1 100644 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/template/ViewResolverPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerPropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.template; +package org.springframework.boot.autoconfigure.freemarker; import java.nio.charset.StandardCharsets; @@ -25,34 +25,34 @@ import org.springframework.util.MimeTypeUtils; import static org.assertj.core.api.Assertions.assertThat; /** - * Tests for {@link AbstractViewResolverProperties}. + * Tests for {@link FreeMarkerProperties}. * * @author Stephane Nicoll */ -class ViewResolverPropertiesTests { +class FreeMarkerPropertiesTests { @Test void defaultContentType() { - assertThat(new ViewResolverProperties().getContentType()).hasToString("text/html;charset=UTF-8"); + assertThat(new FreeMarkerProperties().getContentType()).hasToString("text/html;charset=UTF-8"); } @Test void customContentTypeDefaultCharset() { - ViewResolverProperties properties = new ViewResolverProperties(); + FreeMarkerProperties properties = new FreeMarkerProperties(); properties.setContentType(MimeTypeUtils.parseMimeType("text/plain")); assertThat(properties.getContentType()).hasToString("text/plain;charset=UTF-8"); } @Test void defaultContentTypeCustomCharset() { - ViewResolverProperties properties = new ViewResolverProperties(); + FreeMarkerProperties properties = new FreeMarkerProperties(); properties.setCharset(StandardCharsets.UTF_16); assertThat(properties.getContentType()).hasToString("text/html;charset=UTF-16"); } @Test void customContentTypeCustomCharset() { - ViewResolverProperties properties = new ViewResolverProperties(); + FreeMarkerProperties properties = new FreeMarkerProperties(); properties.setContentType(MimeTypeUtils.parseMimeType("text/plain")); properties.setCharset(StandardCharsets.UTF_16); assertThat(properties.getContentType()).hasToString("text/plain;charset=UTF-16"); @@ -60,14 +60,10 @@ class ViewResolverPropertiesTests { @Test void customContentTypeWithPropertyAndCustomCharset() { - ViewResolverProperties properties = new ViewResolverProperties(); + FreeMarkerProperties properties = new FreeMarkerProperties(); properties.setContentType(MimeTypeUtils.parseMimeType("text/plain;foo=bar")); properties.setCharset(StandardCharsets.UTF_16); assertThat(properties.getContentType()).hasToString("text/plain;charset=UTF-16;foo=bar"); } - static class ViewResolverProperties extends AbstractViewResolverProperties { - - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplatePropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplatePropertiesTests.java new file mode 100644 index 0000000000..7ad619a1f2 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure-all/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplatePropertiesTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012-2025 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 + * + * https://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.groovy.template; + +import java.nio.charset.StandardCharsets; + +import org.junit.jupiter.api.Test; + +import org.springframework.util.MimeTypeUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link GroovyTemplateProperties}. + * + * @author Stephane Nicoll + */ +class GroovyTemplatePropertiesTests { + + @Test + void defaultContentType() { + assertThat(new GroovyTemplateProperties().getContentType()).hasToString("text/html;charset=UTF-8"); + } + + @Test + void customContentTypeDefaultCharset() { + GroovyTemplateProperties properties = new GroovyTemplateProperties(); + properties.setContentType(MimeTypeUtils.parseMimeType("text/plain")); + assertThat(properties.getContentType()).hasToString("text/plain;charset=UTF-8"); + } + + @Test + void defaultContentTypeCustomCharset() { + GroovyTemplateProperties properties = new GroovyTemplateProperties(); + properties.setCharset(StandardCharsets.UTF_16); + assertThat(properties.getContentType()).hasToString("text/html;charset=UTF-16"); + } + + @Test + void customContentTypeCustomCharset() { + GroovyTemplateProperties properties = new GroovyTemplateProperties(); + properties.setContentType(MimeTypeUtils.parseMimeType("text/plain")); + properties.setCharset(StandardCharsets.UTF_16); + assertThat(properties.getContentType()).hasToString("text/plain;charset=UTF-16"); + } + + @Test + void customContentTypeWithPropertyAndCustomCharset() { + GroovyTemplateProperties properties = new GroovyTemplateProperties(); + properties.setContentType(MimeTypeUtils.parseMimeType("text/plain;foo=bar")); + properties.setCharset(StandardCharsets.UTF_16); + assertThat(properties.getContentType()).hasToString("text/plain;charset=UTF-16;foo=bar"); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/PathBasedTemplateAvailabilityProvider.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/PathBasedTemplateAvailabilityProvider.java similarity index 98% rename from spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/PathBasedTemplateAvailabilityProvider.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/PathBasedTemplateAvailabilityProvider.java index 892af9a3e5..d221a63058 100644 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/PathBasedTemplateAvailabilityProvider.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/PathBasedTemplateAvailabilityProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 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. diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvider.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvider.java similarity index 96% rename from spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvider.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvider.java index 4f7ecb6f60..0aa06ea5ca 100644 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvider.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 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. diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProviders.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProviders.java similarity index 100% rename from spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProviders.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProviders.java diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateLocation.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateLocation.java similarity index 100% rename from spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateLocation.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateLocation.java diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateRuntimeHints.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateRuntimeHints.java similarity index 100% rename from spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/TemplateRuntimeHints.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateRuntimeHints.java diff --git a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/package-info.java similarity index 92% rename from spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/package-info.java rename to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/package-info.java index b29af3c39f..94332cdb8b 100644 --- a/spring-boot-project/spring-boot-autoconfigure-all/src/main/java/org/springframework/boot/autoconfigure/template/package-info.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2025 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. diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories index 169920a7e7..e8b017f471 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories @@ -3,3 +3,6 @@ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingP org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter=\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer + +org.springframework.aot.hint.RuntimeHintsRegistrar=\ +org.springframework.boot.autoconfigure.template.TemplateRuntimeHints