配置设置

Settings(配置设置) 是影响FreeMarker行为的已被命名的值。配置设置有很多, 例如:localenumber_formatdefault_encodingtemplate_exception_handler。可以参考 Configuration.setSetting(...)的Java API 文档 来查看配置设置的完整列表。

配置设置存储在 Configuration 实例中,可以在 Template 实例中被覆盖。比如,在配置中给 locale 设置为 "en_US", 那么使用该配置的所有模板中的 locale 都使用 "en_US", 除非在模板中locale被明确地设置成其它不同的值(参见 localization)。 因此,在 Configuration 中的值充当默认值, 这些值在每个模板中也可以被覆盖。在 ConfigurationTemplate 实例中的值也可以在单独调用 Template.process 方法后被覆盖。 对于每个调用了 freemarker.core.Environment 对象的值在内部创建时就持有模板执行的运行时环境,也包括了那个级别被覆盖了的设置信息。 在模板执行时,那里存储的值也可以被改变,所以模板本身也可以设置配置信息, 比如在输出中途来变换 locale 设置。

配置信息可以被想象成3层(ConfigurationTemplateEnvironment), 最高层包含特定的值,它为设置信息提供最有效的值。 比如(设置信息A到F仅仅是为这个示例而构想的):

Setting A Setting B Setting C Setting D Setting E Setting F
Layer 3: Environment 1 - - 1 - -
Layer 2: Template 2 2 - - 2 -
Layer 1: Configuration 3 3 3 3 - -

配置信息的有效值为:A=1,B=2,C=3,D=1,E=2。 而F的设置则是 null,或者在你获取它的时候将抛出异常。

我们看看如何准确设置配置信息:

  • Configuration 层: 原则上设置配置信息时使用 Configuration 对象的setter方法,例如:

    Configuration myCfg = new Configuration(Configuration.VERSION_2_3_23);
    myCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
    myCfg.setDefaultEncoding("UTF-8");

    在真正使用 Configuration 对象 (通常在初始化应用程序时)之前来配置它,后面必须将其视为只读的对象。

    在实践中,比如很多Web应用框架中,就应该使用这种框架特定的配置方式来进行配置, 比如使用成对的 String 来配置(像在 .properties 属性配置文件中那样)。 在这种情况下,框架的作者大多数使用 Configuration 对象的 setSetting(String name, String value) 方法。 这可以参考setSetting的API文档 部分来获取可用的设置名和参数的格式的信息。 而在Spring框架中,我们可以这样进行:

    <bean id="freemarkerConfig"
        class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
      <property name="freemarkerSettings">
        <props>
          <prop key="incompatible_improvements">2.3.23</prop>
          <prop key="template_exception_handler">rethrow</prop>
          <prop key="default_encoding">UTF-8</prop>
        </props>
      </property>
    </bean>

    请注意,这种形式的配置( String 键-值对) 和直接使用 Configuration 的API相比, 很不幸地被限制了。

  • Template 层:对于被请求的本地化信息,模板的 locale 设置由 Configuration.getTemplate(...) 来设置。 否则,就不能在这里进行设置,除非想控制 Template 对象来代替 freemarker.cache.TemplateCache,这样的话, 应该在 Template 对象第一次被使用前就设置配置信息, 然后就将 Template 对象视为是只读的。

  • Environment 层:这里有两种配置方法:

    • 使用Java API:使用 Environment 对象的setter方法。当然想要在模板执行之前来做,然后当调用 myTemplate.process(...) 时会遇到问题, 因为在内部创建 Environment 对象后立即就执行模板了, 导致没有机会来进行设置。这个问题的解决可以用下面两个步骤进行:

      Environment env = myTemplate.createProcessingEnvironment(root, out);
      env.setLocale(java.util.Locale.ITALY);
      env.setNumberFormat("0.####");
      env.process();  // process the template
    • 在模板中(通常这被认为是不好的做法)直接使用 setting 指令,例如:

      <#setting locale="it_IT">
      <#setting number_format="0.####">

    在这层,当什么时候改变配置信息,是没有限制的。

要知道 FreeMarker 支持什么样的配置信息还有它们的意义, 可以先看看FreeMarker Java API文档中的下面这部分内容:

  • 在三层中 freemarker.core.Configurable 的setter方法来配置。

  • 只在 Configuration 层可用的 freemarker.template.Configuration 的setter方法来配置。

  • 在三层中可用 String 键-值对书写的 freemarker.core.Configurable.setSetting(String,String) 配置。

  • 只在 Configuration 层中可用 String 键-值对书写的 freemarker.template.Configuration.setSetting(String, String) 配置。