2

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

按照此处的文档,我设置了一个非常简单的示例,如下所示

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.

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

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

我对这种情况感到有些惊讶 - 即 Freemarker 似乎需要 getter 并且不能与开箱即用的公共字段一起工作。我故意在我的模型对象上使用公共字段而不是 getter/setter,因此添加 getter 只是为了使 Freemarker 工作不是我会考虑的解决方案。

我搜索了很多并通读了 Freemarker 文档,但找不到任何方法在 Freemarker 中“打开”这种行为。可能吗?

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


根据评论进行编辑-我知道 Freemarker 这样做(坚持使用 getters 开箱即用)遵循 Java Beans 规范,但 Java 生态系统中的大多数库都支持公共领域 - Hibernate 和 Jackson 是突出的例子 - 在我个人看来它作为一个同样有效的标准,并且发现不支持它的库令人惊讶。

4

2 回答 2

5

这一切都取决于objectWrapper配置设置。大多数项目使用的DefaultObjectWrapper(和任何子BeansWrapper类)都有一个exposeFields可以设置为true.

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

viewRendererConfiguration:
  freemarker:  # was `.ftl:` before Dropwizard 1.3.0
    objectWrapper=DefaultObjectWrapper(2.3.28, exposeFields=true)
于 2019-06-22T07:02:34.357 回答
1

它在freemarker 文档中说明

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

请注意,它也遵循java 封装概念

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

于 2019-06-18T03:40:08.790 回答