|
|
|
@ -16,6 +16,13 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.web.servlet.view.freemarker; |
|
|
|
package org.springframework.web.servlet.view.freemarker; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.Locale; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import freemarker.template.Configuration; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
import org.springframework.web.servlet.View; |
|
|
|
import org.springframework.web.servlet.view.AbstractTemplateViewResolver; |
|
|
|
import org.springframework.web.servlet.view.AbstractTemplateViewResolver; |
|
|
|
import org.springframework.web.servlet.view.AbstractUrlBasedView; |
|
|
|
import org.springframework.web.servlet.view.AbstractUrlBasedView; |
|
|
|
|
|
|
|
|
|
|
|
@ -29,12 +36,19 @@ import org.springframework.web.servlet.view.AbstractUrlBasedView; |
|
|
|
* <p><b>Note:</b> To ensure that the correct encoding is used when the rendering |
|
|
|
* <p><b>Note:</b> To ensure that the correct encoding is used when the rendering |
|
|
|
* the response, set the {@linkplain #setContentType(String) content type} with an |
|
|
|
* the response, set the {@linkplain #setContentType(String) content type} with an |
|
|
|
* appropriate {@code charset} attribute — for example, |
|
|
|
* appropriate {@code charset} attribute — for example, |
|
|
|
* {@code "text/html;charset=UTF-8"}. |
|
|
|
* {@code "text/html;charset=UTF-8"}; however, as of Spring Framework 6.2, it is |
|
|
|
|
|
|
|
* no longer strictly necessary to explicitly set the content type in the |
|
|
|
|
|
|
|
* {@code FreeMarkerViewResolver} if you have set an explicit encoding via either |
|
|
|
|
|
|
|
* {@link FreeMarkerView#setEncoding(String)}, |
|
|
|
|
|
|
|
* {@link FreeMarkerConfigurer#setDefaultEncoding(String)}, or |
|
|
|
|
|
|
|
* {@link Configuration#setDefaultEncoding(String)}. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p><b>Note:</b> When chaining ViewResolvers, a {@code FreeMarkerViewResolver} will |
|
|
|
* <p><b>Note:</b> When chaining ViewResolvers, a {@code FreeMarkerViewResolver} will |
|
|
|
* check for the existence of the specified template resources and only return |
|
|
|
* check for the existence of the specified template resources and only return |
|
|
|
* a non-null {@code View} object if the template was actually found. |
|
|
|
* a non-null {@code View} object if the template was actually found. |
|
|
|
* |
|
|
|
* |
|
|
|
|
|
|
|
* <p>Note: Spring's FreeMarker support requires FreeMarker 2.3.26 or higher. |
|
|
|
|
|
|
|
* |
|
|
|
* @author Juergen Hoeller |
|
|
|
* @author Juergen Hoeller |
|
|
|
* @author Sam Brannen |
|
|
|
* @author Sam Brannen |
|
|
|
* @since 1.1 |
|
|
|
* @since 1.1 |
|
|
|
@ -83,4 +97,65 @@ public class FreeMarkerViewResolver extends AbstractTemplateViewResolver { |
|
|
|
return (getViewClass() == FreeMarkerView.class ? new FreeMarkerView() : super.instantiateView()); |
|
|
|
return (getViewClass() == FreeMarkerView.class ? new FreeMarkerView() : super.instantiateView()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Delegates to {@code super.loadView(viewName, locale)} for standard behavior |
|
|
|
|
|
|
|
* and then to {@link #postProcessView(FreeMarkerView)} for customization. |
|
|
|
|
|
|
|
* @since 6.2 |
|
|
|
|
|
|
|
* @see org.springframework.web.servlet.view.UrlBasedViewResolver#loadView(String, Locale) |
|
|
|
|
|
|
|
* @see #postProcessView(FreeMarkerView) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
|
|
|
protected View loadView(String viewName, Locale locale) throws Exception { |
|
|
|
|
|
|
|
View view = super.loadView(viewName, locale); |
|
|
|
|
|
|
|
if (view instanceof FreeMarkerView freeMarkerView) { |
|
|
|
|
|
|
|
postProcessView(freeMarkerView); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return view; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Post process the supplied {@link FreeMarkerView} after it has been {@linkplain |
|
|
|
|
|
|
|
* org.springframework.web.servlet.view.UrlBasedViewResolver#loadView(String, Locale) |
|
|
|
|
|
|
|
* loaded}. |
|
|
|
|
|
|
|
* <p>The default implementation attempts to override the |
|
|
|
|
|
|
|
* {@linkplain org.springframework.web.servlet.view.AbstractView#setContentType(String) |
|
|
|
|
|
|
|
* content type} of the view with {@code "text/html;charset=<encoding>"}, |
|
|
|
|
|
|
|
* where {@code <encoding>} is equal to an explicitly configured character |
|
|
|
|
|
|
|
* encoding for the underlying FreeMarker template file. If an explicit content |
|
|
|
|
|
|
|
* type has been configured for this view resolver or if no explicit character |
|
|
|
|
|
|
|
* encoding has been configured for the template file, this method does not |
|
|
|
|
|
|
|
* modify the supplied {@code FreeMarkerView}. |
|
|
|
|
|
|
|
* @since 6.2 |
|
|
|
|
|
|
|
* @see #loadView(String, Locale) |
|
|
|
|
|
|
|
* @see #setContentType(String) |
|
|
|
|
|
|
|
* @see org.springframework.web.servlet.view.AbstractView#setContentType(String) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected void postProcessView(FreeMarkerView freeMarkerView) { |
|
|
|
|
|
|
|
// If an explicit content type has been configured for all views, it has
|
|
|
|
|
|
|
|
// already been set in the view in UrlBasedViewResolver#buildView(String),
|
|
|
|
|
|
|
|
// and there is no need to override it here.
|
|
|
|
|
|
|
|
if (getContentType() != null) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if the view has an explicit encoding set.
|
|
|
|
|
|
|
|
String encoding = freeMarkerView.getEncoding(); |
|
|
|
|
|
|
|
if (encoding == null) { |
|
|
|
|
|
|
|
// If an explicit encoding has not been configured for this particular view,
|
|
|
|
|
|
|
|
// use the explicit default encoding for the FreeMarker Configuration, if set.
|
|
|
|
|
|
|
|
Configuration configuration = freeMarkerView.obtainConfiguration(); |
|
|
|
|
|
|
|
if (configuration.isDefaultEncodingExplicitlySet()) { |
|
|
|
|
|
|
|
encoding = configuration.getDefaultEncoding(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (StringUtils.hasText(encoding)) { |
|
|
|
|
|
|
|
String contentType = "text/html;charset=" + encoding; |
|
|
|
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
|
|
|
logger.debug("Setting Content-Type for view [%s] to: %s".formatted(freeMarkerView, contentType)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
freeMarkerView.setContentType(contentType); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|