Freemarker:访问模板中没有 getter 的 public 字段
Freemarker: access public field with no getter in template
我正在 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
时的预期输出是 HTML 显示 Hello World
的文档。
实际发生的是 Freemarker 抛出异常,抱怨 ${foo.bar}
- 特别是 bar
- 未定义。
这似乎是因为 bar
是一个 public 字段,没有 getter。当我将 public String getBar() { return bar; }
getter 添加到 Foo
时,它起作用了。
我对这种情况感到有些惊讶 - 即 Freemarker 似乎需要 getters 并且不能使用开箱即用的 public 字段。我故意在我的模型对象上使用 public 字段而不是 getters/setters,因此添加 getter 只是为了让 Freemarker 工作不是我会考虑的解决方案。
我在谷歌上搜索了很多,通读了 Freemarker 文档,但找不到任何方法来 'turn on' Freemarker 中的这种行为。 可能吗?
只是为了兴趣——我也尝试了上面的例子,完全一样,但是使用 Mustache 模板和 public 字段在那里工作正常(即 {{foo.bar}}
渲染 Hello World
没有问题).这解决了眼前的问题,所以这个问题主要是出于好奇,或者以防万一我出于其他原因决定使用 Freemarker 而不是 Mustache。
根据评论编辑 - 我知道 Freemarker 这样做(坚持 getter 开箱即用)以遵循 Java Beans 规范,但是 Java 生态系统中的大多数库都支持 public 字段 - Hibernate 和 Jackson 是突出的例子 - 在某种程度上我个人认为它是一个同样有效的标准并且发现库不支持它盒子令人惊讶。
中有说明
Every object will be wrapped into a TemplateHashModel that will expose JavaBeans properties and methods of the object. This way, you can use model.foo in the template to invoke obj.getFoo() or obj.isFoo() methods. (Note that public fields are not visible directly; you must write a getter method for them.)
注意它也跟着java encapsulation concept
您也可以使用框架作为 lombok getters 自动使用仅 class 注释
这完全取决于 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)
我正在 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
时的预期输出是 HTML 显示 Hello World
的文档。
实际发生的是 Freemarker 抛出异常,抱怨 ${foo.bar}
- 特别是 bar
- 未定义。
这似乎是因为 bar
是一个 public 字段,没有 getter。当我将 public String getBar() { return bar; }
getter 添加到 Foo
时,它起作用了。
我对这种情况感到有些惊讶 - 即 Freemarker 似乎需要 getters 并且不能使用开箱即用的 public 字段。我故意在我的模型对象上使用 public 字段而不是 getters/setters,因此添加 getter 只是为了让 Freemarker 工作不是我会考虑的解决方案。
我在谷歌上搜索了很多,通读了 Freemarker 文档,但找不到任何方法来 'turn on' Freemarker 中的这种行为。 可能吗?
只是为了兴趣——我也尝试了上面的例子,完全一样,但是使用 Mustache 模板和 public 字段在那里工作正常(即 {{foo.bar}}
渲染 Hello World
没有问题).这解决了眼前的问题,所以这个问题主要是出于好奇,或者以防万一我出于其他原因决定使用 Freemarker 而不是 Mustache。
根据评论编辑 - 我知道 Freemarker 这样做(坚持 getter 开箱即用)以遵循 Java Beans 规范,但是 Java 生态系统中的大多数库都支持 public 字段 - Hibernate 和 Jackson 是突出的例子 - 在某种程度上我个人认为它是一个同样有效的标准并且发现库不支持它盒子令人惊讶。
Every object will be wrapped into a TemplateHashModel that will expose JavaBeans properties and methods of the object. This way, you can use model.foo in the template to invoke obj.getFoo() or obj.isFoo() methods. (Note that public fields are not visible directly; you must write a getter method for them.)
注意它也跟着java encapsulation concept
您也可以使用框架作为 lombok getters 自动使用仅 class 注释
这完全取决于 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)