Freemarker:访问公共字段,模板中没有吸气剂

时间:2019-06-17 23:37:40

标签: java freemarker dropwizard public-members dropwizard-templates

我正在Dropwizard应用程序中设置视图,并遇到了Freemarker的奇怪问题。

docs here之后,我建立了一个非常简单的示例,如下所示:

public class ExampleFreemarkerView extends View {
  private Foo foo;

  public ContractHtmlView(Foo Foo) {
    super("FooView.ftl");
    this.foo = foo;
  }

  public Contract getFoo() { return foo };
}

public class Foo {
  public String bar = "Hello World";
}

使用FooView.ftl

<html>
  <body>
    <h1>${foo.bar}</h1>
  </body>
</html>

渲染ExampleFreemarkerView是显示Hello World的HTML文档时的预期输出。

实际上发生的是Freemarker引发异常,抱怨${foo.bar}-特别是bar-未定义。

这似乎是因为bar是一个公共领域,没有吸气剂。当我向public String getBar() { return bar; }添加Foo吸气剂时,它会起作用。

我确实对这种情况感到有些惊讶-也就是说,Freemarker似乎需要使用吸气剂,并且无法直接使用公共领域。我故意在模型对象上使用公共字段,而不是使用getter / setter,因此,我不考虑添加getter来使Freemarker正常工作。

我在Google上搜索了很多内容,并阅读了Freemarker文档,但找不到任何方法可以在Freemarker中“打开”此行为。 有可能吗?

仅出于兴趣-我也尝试了上面的示例,但完全相同,但是使用Mustache模板和公共字段可以正常工作(即{{foo.bar}}呈现Hello World没问题)。这就解决了眼前的问题,所以这个问题主要是出于好奇,或者万一我出于其他原因决定使用Freemarker替代Mustache。


基于评论进行编辑-我了解Freemarker这样做(坚持使用吸气剂)是为了遵循Java Beans规范,但是Java生态系统中的大多数库都支持公共字段- Hibernate和Jackson是杰出的例子-就我个人而言,它是同等有效的标准,并且发现不支持它的库令人惊讶。

2 个答案:

答案 0 :(得分:2)

这全部取决于objectWrapper的配置设置。大多数项目正在使用的DefaultObjectWrapper(以及任何BeansWrapper子类)具有exposeFields设置,可以将其设置为true

在Dropwizard中,如果以兼容的方式(基于https://github.com/apache/freemarker-online-tester)设置ViewBundle,则可以在配置YML中这样完成:

viewRendererConfiguration:
  freemarker:  # was `.ftl:` before Dropwizard 1.3.0
    objectWrapper=DefaultObjectWrapper(2.3.28, exposeFields=true)

答案 1 :(得分:1)

freemarker docs

中有说明
  

每个对象都将被包装到一个TemplateHashModel中,该模板将公开该对象的JavaBeans属性和方法。这样,您可以在模板中使用model.foo来调用obj.getFoo()或obj.isFoo()方法。 (请注意,公共字段不是直接可见的;您必须为它们编写一个getter方法。)

请注意,它也遵循java encapsulation concept

您还可以仅使用类注释自动将框架用作lombok getters