org.thymeleaf.spring5.view.AbstractThymeleafView Maven / Gradle / Ivy
Show all versions of thymeleaf-spring5 Show documentation
/*
* =============================================================================
*
* Copyright (c) 2011-2018, The THYMELEAF team (http://www.thymeleaf.org)
*
* 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.thymeleaf.spring5.view;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.web.context.support.WebApplicationObjectSupport;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.support.RequestContext;
import org.thymeleaf.spring5.ISpringTemplateEngine;
import org.thymeleaf.spring5.SpringTemplateEngine;
/**
*
* Abstract implementation class of the Spring MVC {@link org.springframework.web.servlet.View}
* interface for Thymeleaf.
*
*
* Views represent a template being executed, after being resolved (and
* instantiated) by a {@link org.springframework.web.servlet.ViewResolver}.
*
*
* @author Daniel Fernández
* @author Josh Long
*
* @since 3.0.3
*
*/
public abstract class AbstractThymeleafView
extends WebApplicationObjectSupport
implements View, BeanNameAware {
/**
*
* Default charset set to ISO-8859-1 for compatibility reasons with Spring's AbstractView.
* Value is {@code "text/html;charset=ISO-8859-1"}.
*
*/
public static final String DEFAULT_CONTENT_TYPE = "text/html;charset=ISO-8859-1";
/**
*
* By default Thymeleaf will not wait until a template is fully processed and rendered before
* starting to output its results. Instead, it will start producing output as soon as possible
* while the template is still being processed. Value is {@code true}.
*
*/
public static final boolean DEFAULT_PRODUCE_PARTIAL_OUTPUT_WHILE_PROCESSING = true;
private String beanName = null;
private String contentType = DEFAULT_CONTENT_TYPE;
private boolean contentTypeSet = false;
private boolean forceContentType = false;
private boolean forceContentTypeSet = false;
private String characterEncoding = null;
private boolean producePartialOutputWhileProcessing = DEFAULT_PRODUCE_PARTIAL_OUTPUT_WHILE_PROCESSING;
private boolean producePartialOutputWhileProcessingSet = false;
private ISpringTemplateEngine templateEngine = null;
private String templateName = null;
private Locale locale = null;
private Map staticVariables = null;
/**
*
* Creates a new instance of {@code ThymeleafView}.
*
*/
protected AbstractThymeleafView() {
super();
}
/**
*
* Creates a new instance of {@code ThymeleafView}, specifying the
* template name.
*
*
* @param templateName the template name.
*/
protected AbstractThymeleafView(final String templateName) {
super();
this.templateName = templateName;
}
/**
*
* Returns the content type that will used for this view.
*
*
* Content type will be computed this way:
*
*
* - If a value is specified calling {@link #setContentType(String)} on
* this object, that value will be used.
* - If a value is specified at the view resolver by calling
* {@link ThymeleafViewResolver#setContentType(String)}, that one will
* be used.
* - If none of the above is true, the {@link #DEFAULT_CONTENT_TYPE} constant
* with value {@value #DEFAULT_CONTENT_TYPE} will be used.
*
*
* @return the content type
* @see ThymeleafViewResolver#getContentType()
*/
public String getContentType() {
return this.contentType;
}
/**
*
* Sets the content type that will used for this view.
*
*
* Content type will be computed this way:
*
*
* - If a value is specified calling this method, that value will be used.
* - If a value is specified at the view resolver by calling
* {@link ThymeleafViewResolver#setContentType(String)}, that one will
* be used.
* - If none of the above is true, the {@link #DEFAULT_CONTENT_TYPE} constant
* with value {@value #DEFAULT_CONTENT_TYPE} will be used.
*
*
* @param contentType the content type to be used.
* @see ThymeleafViewResolver#setContentType(String)
*/
public void setContentType(final String contentType) {
this.contentType = contentType;
this.contentTypeSet = true;
}
/*
* Internally used (by ThymeleafViewResolver) in order to know whether a value
* for the content type has been explicitly set or not.
*/
protected boolean isContentTypeSet() {
return this.contentTypeSet;
}
/**
*
* Returns whether the configured content type should be forced instead of attempting
* a smart content type application based on template name.
*
*
* When forced, the configured content type ({@link #setForceContentType(boolean)}) will
* be applied even if the template name ends in a known suffix:
* {@code .html}, {@code .htm}, {@code .xhtml},
* {@code .xml}, {@code .js}, {@code .json},
* {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}.
*
* Default value is {@code false}
.
*
* @return whether the content type will be forced or not.
* @since 3.0.6
*/
public boolean getForceContentType() {
return this.forceContentType;
}
/**
*
* Sets whether the configured content type should be forced instead of attempting
* a smart content type application based on template name.
*
*
* When forced, the configured content type ({@link #setForceContentType(boolean)}) will
* be applied even if the template name ends in a known suffix:
* {@code .html}, {@code .htm}, {@code .xhtml},
* {@code .xml}, {@code .js}, {@code .json},
* {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}.
*
* Default value is {@code false}
.
*
* @param forceContentType whether the configured template mode should be forced or not.
* @since 3.0.6
*/
public void setForceContentType(final boolean forceContentType) {
this.forceContentType = forceContentType;
this.forceContentTypeSet = true;
}
/*
* Internally used (by ThymeleafViewResolver) in order to know whether a value
* for the "force content type" flag has been explicitly set or not.
* @since 3.0.6
*/
protected boolean isForceContentTypeSet() {
return this.forceContentTypeSet;
}
/**
*
* Returns the character encoding set to be used for rendering this view.
*
*
* Many times, character encoding is specified as a part of the content
* type using the {@link #setContentType(String)} method, but this is not mandatory,
* and it could be that only the MIME type is specified that way, thus allowing
* to set the character encoding using the {@link #setCharacterEncoding(String)}
* counterpart of this getter method.
*
*
* @return the character encoding.
*/
public String getCharacterEncoding() {
return this.characterEncoding;
}
/**
*
* Specifies the character encoding to be set into the response when
* the view is rendered.
*
*
* Many times, character encoding is specified as a part of the content
* type using the {@link #setContentType(String)} method, but this is not mandatory,
* and it could be that only the MIME type is specified that way, thus allowing
* to set the character encoding using this method.
*
*
* @param characterEncoding the character encoding to be used (e.g. {@code UTF-8},
* {@code ISO-8859-1}, etc.)
*/
public void setCharacterEncoding(final String characterEncoding) {
this.characterEncoding = characterEncoding;
}
/**
*
* Returns whether Thymeleaf should start producing output –and sending it to the web server's output
* buffers– as soon as possible, outputting partial results while processing as they become available so
* that they can potentially be sent to the client (browser) before processing of the whole template has
* completely finished.
*
*
* If set to {@code false}, no fragments of template result will be sent to the web server's
* output buffers until Thymeleaf completely finishes processing the template and generating
* the corresponding output. Only once finished will output start to be written to the web server's
* output buffers, and therefore sent to the clients.
*
*
* Note that setting this to {@code false} is not recommended for most
* scenarios, as it can (very) significantly increase the amount of memory used per
* template execution. Only modify this setting if you know what you are doing. A typical
* scenario in which setting this to {@code false} could be of use is when an application is
* suffering from UI rendering issues (flickering) at the browser due to incremental
* rendering of very large templates.
*
*
* Default value is {@code true}.
*
*
* @return whether to start producing output as soon as possible while processing or not (default: {@code true}).
* @since 3.0.10
*/
public boolean getProducePartialOutputWhileProcessing() {
return this.producePartialOutputWhileProcessing;
}
/**
*
* Sets whether Thymeleaf should start producing output –and sending it to the web server's output
* buffers– as soon as possible, outputting partial results while processing as they become available so
* that they can potentially be sent to the client (browser) before processing of the whole template has
* completely finished.
*
*
* If set to {@code false}, no fragments of template result will be sent to the web server's
* output buffers until Thymeleaf completely finishes processing the template and generating
* the corresponding output. Only once finished will output start to be written to the web server's
* output buffers, and therefore sent to the clients.
*
*
* Note that setting this to {@code false} is not recommended for most
* scenarios, as it can (very) significantly increase the amount of memory used per
* template execution. Only modify this setting if you know what you are doing. A typical
* scenario in which setting this to {@code false} could be of use is when an application is
* suffering from UI rendering issues (flickering) at the browser due to incremental
* rendering of very large templates.
*
*
* Default value is {@code true}.
*
*
* @param producePartialOutputWhileProcessing whether to start producing output as soon as possible while
* processing or not (default: {@code true}).
* @since 3.0.10
*/
public void setProducePartialOutputWhileProcessing(final boolean producePartialOutputWhileProcessing) {
this.producePartialOutputWhileProcessing = producePartialOutputWhileProcessing;
this.producePartialOutputWhileProcessingSet = true;
}
/*
* Internally used (by ThymeleafViewResolver) in order to know whether a value
* for the "producePartialOutputWhileProcessing" flag has been explicitly set or not.
* @since 3.0.10
*/
protected boolean isProducePartialOutputWhileProcessingSet() {
return this.producePartialOutputWhileProcessingSet;
}
/**
*
* Returns the bean name.
*
*
* @return the bean name.
*/
public String getBeanName() {
return this.beanName;
}
/**
*
* Sets the bean name.
*
*
* @param beanName the new bean name.
*/
public void setBeanName(final String beanName) {
this.beanName = beanName;
}
/**
*
* Returns the name of the template being processed by this view object.
*
*
* This name will be specified in the same shape it will be resolved by the
* template resolvers (i.e. as it is returned by controllers, without any
* prefixes/suffixes).
*
*
* @return the template name.
*/
public String getTemplateName() {
return this.templateName;
}
/**
*
* Sets the name of the template to be processed by this view object.
*
*
* This name will be specified in the same shape it will be resolved by the
* template resolvers (i.e. as it is returned by controllers, without any
* prefixes/suffixes).
*
*
* @param templateName the template name
*/
public void setTemplateName(final String templateName) {
this.templateName = templateName;
}
/**
*
* Returns the locale to be used for template processing.
*
*
* @return the locale
*/
protected Locale getLocale() {
return this.locale;
}
/**
*
* Sets the locale to be used for template processing. Usually,
* the View Resolver will set this automatically from user session
* / application data.
*
*
* @param locale the locale to be used.
*/
protected void setLocale(final Locale locale) {
this.locale = locale;
}
/**
*
* Returns the template engine instance –a {@link SpringTemplateEngine} instance,
* specifically– to be used for processing the template specified by this view object.
*
*
* @return the template engine instance
*/
protected ISpringTemplateEngine getTemplateEngine() {
return this.templateEngine;
}
/**
*
* Sets the template engine instance –a {@link SpringTemplateEngine} instance,
* specifically– to be used for processing the template specified by this view object.
*
*
* @param templateEngine the template engine instance to be used
*/
protected void setTemplateEngine(final ISpringTemplateEngine templateEngine) {
this.templateEngine = templateEngine;
}
/**
*
* Return the static variables, which will be available at the context
* every time this view is processed.
*
*
* These static variables are added to the context before the view is
* processed, so that they can be referenced from the context like any
* other context variables, for example: {@code ${myStaticVar}}.
*
*
* @return the map of static variables to be set into view's execution.
*/
public Map getStaticVariables() {
if (this.staticVariables == null) {
return Collections.emptyMap();
}
return Collections.unmodifiableMap(this.staticVariables);
}
/**
*
* Add a new static variable.
*
*
* These static variables are added to the context before this view
* is processed, so that they can be referenced from
* the context like any other context variables, for example:
* {@code ${myStaticVar}}.
*
*
* @param name the name of the static variable
* @param value the value of the static variable
*/
public void addStaticVariable(final String name, final Object value) {
if (this.staticVariables == null) {
this.staticVariables = new HashMap(3, 1.0f);
}
this.staticVariables.put(name, value);
}
/**
*
* Sets a set of static variables, which will be available at the context
* when this view is processed.
*
*
* This method does not overwrite the existing static variables, it
* simply adds the ones specify to any variables already registered.
*
*
* These static variables are added to the context before this view is
* processed, so that they can be referenced from
* the context like any other context variables, for example:
* {@code ${myStaticVar}}.
*
*
*
* @param variables the set of variables to be added.
*/
public void setStaticVariables(final Map variables) {
if (variables != null) {
if (this.staticVariables == null) {
this.staticVariables = new HashMap(3, 1.0f);
}
this.staticVariables.putAll(variables);
}
}
protected static void addRequestContextAsVariable(
final Map model, final String variableName, final RequestContext requestContext)
throws ServletException {
if (model.containsKey(variableName)) {
throw new ServletException(
"Cannot expose request context in model attribute '" + variableName +
"' because an existing model object of the same name");
}
model.put(variableName, requestContext);
}
}