【问题标题】:How to have Freemarker use java.util.Date instead of org.mozilla.javascript.NativeDate in Alfresco?如何让 Freemarker 在 Alfresco 中使用 java.util.Date 而不是 org.mozilla.javascript.NativeDate?
【发布时间】:2012-10-09 17:44:07
【问题描述】:

这可能是接近 Alfresco 的人的问题,因为它有点具体。

我在创建网站时添加了一个自定义方面,它拥有日期类型的属性:

<type>d:date</type>

现在,我正在扩展 site.lib.ftl 文件以显示此日期:

"startdate": "<#if site.node.hasAspect("my:customAspect")>${siteNode.properties["my:customAspectDate"]?string("yyyy-MM-dd")}</#if>",

由于无法访问宏本身的 site.node,我扩展了宏参数列表:

<#macro siteJSONManagers site siteNode roles>

所以我可以从 site.get.json.ftl 以及 person.sites.get.json.ftl 调用它:

<@siteLib.siteJSON site=site siteNode=siteNode />

现在,对于 site.get.js,我在 javascript 中准备了 sitenode:

model.siteNode = site.node; // or the same with site.getNode;

我的日期被正确解析。 但是,当从 person.sites.get.json.ftl 调用宏时,我无法在 javascript 控制器中准备 site.node,所以我在 freemarker 中进行(通过直接调用):

<@siteLib.siteJSONManagers site=site siteNode=site.node roles=roles/>

在使用这个表单时,我得到了这个异常:

"09090011 Wrapped Exception (with status template): 09090096 Error during processing of the template 'Expected method. siteNode.properties[\"my:customAspectDate\"]?string evaluated instead to freemarker.template.SimpleScalar on line 59, column 71 in org\/alfresco\/repository\/site\/site.lib.ftl.'. Please contact your system administrator."

如果我只显示这个标量 (${siteNode.properties["my:customAspectDate"]}),我会在生成的 JSON 中得到 org.mozilla.javascript.NativeDate 作为字符串:

"startdate": "org.mozilla.javascript.NativeDate@7a6e5e2e",

我可以通过在 site.get.json.ftl 中为 siteNode 设置相同的参数来重复此操作。 如果我使用 siteNode.properties["cm:created"],我什至可以重复它。

在我看来,当 javascript 控制器从节点创建模型对象时,创建的日期道具被创建为 java.util.Date 或 Freemarker 使用的任何内容,并且当 Freemarker 本身创建该属性时,它将被转进入 org.mozilla.javascript.NativeDate。

谁能指出我如何改进我的代码以显示日期?我可以使用什么来让我的调用获得相同的值?

如果有什么不同的话,我正在使用来自 SVN HEAD 的 Alfresco。

【问题讨论】:

    标签: alfresco freemarker


    【解决方案1】:

    如果人们经常在 Alfresco 中与 Rhino 一起工作,那么应该在那里解决这个问题。发生的事情是这样的:FreeMarker 模板不直接使用 java.util.Date 作为日期,而是使用 freemareker.template.TemplateDateModel。 FreeMarker 有一个名为object_wrapper 的设置,它是一个将对象转换为freemareker.template.Template{Something}Model-s 的对象。显然,Alfresco 使用的对象包装器不知道org.mozilla.javascript.NativeDate,它使用toString() 将其转换为TemplateScalarModel(这是FreeMarker 的字符串类型)。因此,yourDate?string,其中yourDate 是 FreeMarker 字符串 (TemplateScalarModel) 将只计算为与 yourDate 相同的字符串,因此 (...) 之后将失败(你不能调用字符串) .当yourDate 是 FreeMarker 日期(java.util.Date 正确转换为 TemplateDateModel)时,yourDate?string 评估为格式化程序方法,因此它可以调用它之后的 (...)

    因此,如果在 Alfresco 中使用 Rhino (JavaScript) 对象很常见,他们应该扩展其 ObjectWrapper 以识别 Rhino 对象。也许他们需要做的就是混入freemarker.ext.rhino.RhinoWrapper

    【讨论】:

    • 这就是我认为它不一致的原因。不过,感谢您的广泛解释。
    【解决方案2】:

    您好,您可以在 Freemarker 中使用以下内容:

    ${siteNode.properties["my:customAspectDate"]?date?string("yyyy-MM-dd")}
    

    Alfresco 在活动 Dashlet 中执行此操作:

    活动列表.get.html.ftl

    【讨论】:

    • siteNode.properties["my:customAspectDate"] 不是已经是一个日期(而不是一个看起来像日期的字符串)?因为那?date 部分是多余的。
    • 是的,它是一个日期,但不是 Freemarker 需要/想要的正确日期对象,所以就像有时在 Javascript 中你需要将一个空字符串 "" 附加到一个对象以成为一个字符串。这并不意味着该对象是或不是一个字符串。
    • 我问的原因是提问者回答他自己的问题时,nodeR.properties["my:customAspectDate"]?string("yyyy-MM-dd") 为他工作。这意味着nodeR.properties["my:customAspectDate"] 已经是 FreeMarker 理解的那种日期。如果是org.mozilla.javascript.NativeDate?date 无论如何都不起作用,因为它的字符串值类似于"org.mozilla.javascript.NativeDate@7a6e5e2e",不能被解析为日期。
    • 是的,没错,但这只是在freemarker的上下文中,但如果你检查他的代码,他会通过一个路径在freemarker中查找一个站点,这比仅仅使用“最佳实践”要慢得多像 Alfresco 这样的 javascript 在他们自己的代码中执行。但问题在于日期被转换,所以解决方法是将其转换回freemarkers自己的日期,然后格式化。整个 Alfresco 都在使用它,所以我认为这是要走的路。
    【解决方案3】:

    Aaaaa 并回答我自己的问题,以防其他人也撞到这堵墙两天:

    <#assign nodeR=companyhome.childByNamePath["Sites/" + site.shortName] />
    "startdate": "<#if nodeR.hasAspect("my:customAspect")>${nodeR.properties["my:customAspectDate"]?string("yyyy-MM-dd")}</#if>",
    

    就像我在forum 上所说的那样,我不知道为什么它会以这种方式工作而不是其他方式。

    【讨论】:

      猜你喜欢
      • 2011-12-06
      • 1970-01-01
      • 1970-01-01
      • 2017-05-20
      • 2013-07-12
      • 2011-09-10
      • 2015-03-17
      • 2019-06-12
      • 2016-09-08
      相关资源
      最近更新 更多