【问题标题】:How to make globally shared objects available to freemarker templates in Spring Boot 2如何在 Spring Boot 2 中使全局共享对象可用于 freemarker 模板
【发布时间】:2018-10-09 22:55:32
【问题描述】:

在使用 Spring Boot 2.x 时,在不丢失 Spring Boot 的 FreeMarker 自动配置的情况下,使全局共享对象可用于 freemarker 模板的最佳方法是什么?

执行此操作的底层机制是 Spring Boot 的 FreeMakerConfigurer.setFreemarkerVariables,而后者又调用 FreeMarker 的 Configuration.setAllSharedVariables

但是,除了 Spring Boot 支持的预定义 freemarker 属性之外,没有明显的方法(对我而言)来修改由 FreeMarkerServletWebConfiguration 设置的 FreeMarkerConfigurer。 (搜索“freemarker”here)。

一种常见的方法是创建一个自定义的FreemarkerConfigurer bean,但我相信这样会丢失一些spring boot 提供的自动配置,尤其是在处理各种外部属性方面。

似乎可行的一个选项是使用这样的 BeanPostProcessor:

public class CustomFreeMarkerConfig implements BeanPostProcessor {

    Object sharedWithAllFreeMarkerTemplatesObj = new Object();

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
    throws BeansException {

        if (bean instanceof FreeMarkerConfigurer) {
            FreeMarkerConfigurer configurer = (FreeMarkerConfigurer) bean;

            Map<String, Object> sharedVariables = new HashMap<>();
            sharedVariables.put("obj", sharedWithAllFreeMarkerTemplatesObj);
            configurer.setFreemarkerVariables(sharedVariables);
        }

        return bean;
    }
}

似乎应该有一种更简洁的方法,也许是通过某种方式扩展或配置FreeMarkerConfigurationFactory,但我一直没能找到它。

【问题讨论】:

    标签: spring-boot freemarker


    【解决方案1】:

    I found a solution from spring git

    Spring Boot 2.0 打破了@wo8335224 提供的解决方案,因为 FreeMarkerWebConfiguration 被 FreeMarkerServletWebConfiguration 取代,不幸的是它是包私有的,因此不能被子类化。

    当前可行的解决方案是配置 freemarker.template.Configuration bean:

    @Configuration
    public class FreemarkerConfig {
        public FreemarkerConfig(freemarker.template.Configuration configuration) throws TemplateModelException {
            configuration.setSharedVariable("name", "whatever type of value");
        }
    }
    

    FreeMarkerConfigurer#setFreemarkerVariables 在内部将其工作委托给 freemarker.template.Configuration#setAllSharedVariables。

    【讨论】:

    • 如果您使用这种方法,您将丢失一些 FreeMarker 自动配置。我在我的问题和同一个 git 问题中提到了这一点,我实际上引用了这个问题/答案。也许您不需要自动配置,在这种情况下这是可以接受的。
    • SpringBoot2.3下正常加载如下设置:spring.freemarker.request-context-attribute, spring.freemarker.template-loader-path, spring.freemarker.content-type
    猜你喜欢
    • 2015-12-30
    • 2021-11-27
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-01
    • 2021-01-27
    • 2018-02-25
    相关资源
    最近更新 更多