【问题标题】:Unable to access nested Jsp Tags in Freemarker无法访问 Freemarker 中的嵌套 Jsp 标签
【发布时间】:2013-06-12 17:48:28
【问题描述】:

我写了一个 Jsp 标签库,使用 freemarker 作为视图模板。

custom.tld 放在 META-INF/tags/ 中。

我的标签库被捆绑为 Jar。 customTag.jar。 它有以下模板

AlertTag.ftl
ButtonTag.ftl

AlertTag.ftl 依赖于ButtonTag.ftl

AlertTag.ftl:-

<#assign custom = JspTaglibs["http://www.abc.com/taglibs/custom"]>

<h5>${this.title}</h5>
<div class="alert ${this.typeClass} ${this.classes!}">
   <@custom.button btnType="close" <span class="alt">close</span></@custom.button>
</div>

此 customTag.jar 是另一个网络应用程序的一部分。

web.xml:-

<taglib>
   <taglib-uri>http://www.abc.com/taglibs/custom</taglib-uri>
   <taglib-location>/WEB-INF/custom.tld</taglib-location>
</taglib>

现在当网络应用程序中的index.ftl 尝试使用标签&lt;@custom.Alert id="abc"&gt; 时,它会引发以下异常

Expression JspTaglibs is undefined on line 1, column 17 in freemarker/AlertTag.ftl.
The problematic instruction:
----------
==> assignment: custom=JspTaglibs["http://www.abc.com/taglibs/custom"] [on line 1, column 1 in freemarker/AlertTag.ftl]
----------

Java backtrace for programmers:
----------
freemarker.core.InvalidReferenceException: Expression JspTaglibs is undefined on line 1, column 17 in freemarker/AlertTag.ftl.

我无法在 freemarker 中使用嵌套的 jsp 标签。


AlertTag.java

   Configuration cfg = new Configuration();
    cfg.setClassForTemplateLoading(this.getClass(), "/");

    Template ftlTemplate = cfg.getTemplate(view);
    JspWriter writer = pageContext.getOut();
    data.put("id", id)

    Map<String, Object> rootMap = new HashMap<String,Object>();
    rootMap.put("this", data);
    Environment environment = ftlTemplate.createProcessingEnvironment(rootMap, writer);
    environment.process();
    //ftlTemplate.process(rootMap, writer);

@Daniel,我用过上面的环境,但也没有用。我使用正确吗?

【问题讨论】:

  • 如何调用AlertTag.ftl 本身?
  • 我从 web-app 中的 index.ftl 调用它。 &lt;@custom.Alert id="abc"&gt;
  • I assume @custom.Alert 本身就是一个自定义 JSP 标记,而不是一个普通的 FreeMarker 宏/指令。所以我的意思是如何在技术上调用AlertTag.ftl。因为我怀疑 JSP 标签会创建它自己的 FreeMarker 引擎实例,它与 index.ftl 使用的实例无关,因此根本存在 JSP 标签库支持。
  • 是的,@custom.Alert 是一个自定义 JSP 标记。我编写了一个在 custom.tld 中定义的 AlertTag.java 文件。在 AlertTag.java 中,我正在调用 AlertTag.ftl。让我将其添加到问题中。

标签: jsp jsp-tags freemarker


【解决方案1】:

自定义 JSP 标记支持只是一个 FreeMarker 扩展,它通过专门用于此的 FreeMarker 数据模型实现。 (它恰好是 freemarker.jar 的一部分,但从技术上讲,它也可能是第 3 方扩展。)此数据模型定义了 JspTaglibs 变量等。 (此外,数据模型根不是 Map 或 JavaBean,而是来自彼此叠加的 Servlet 范围。)此数据模型由 FreemarkerSerlvet 设置。

因此,当您在 AlterTag.java 中创建自己的 FreeMarker 引擎和自己的数据模型时,您就切断了这一切。要么您尝试设置一个类似的数据模型(我不知道是否有人设法将其与 FreemarkerServlet...用途。您可以使用 Environment.getCurrentEnvironment() 从 TLS 获取当前环境,然后您可以使用 Environment 方法来包含您的模板,假设模板加载器可以访问它。所以你没有自己的数据模型......相当混乱。

问题是,FreeMarker 旨在使用自己的宏/指令/函数功能来制作库。一些开发人员认为自定义 JSP 标签可以像 FreeMarker 指令一样暴露出来......添加它本身是为了帮助您在“JSP 模型 2”框架内迁移(该模型本身就是一个非常尴尬的 hack,用于在 JSP 上强制 MVC)。如果您将 JSP 支持扩展到此之外……现在,您很有可能需要深入挖掘。

【讨论】:

  • 我已经对问题进行了编辑,并按照您的说法使用了环境变量。请参阅上面的编辑,但 id 没有工作。不太确定,如果我使用正确。
  • 您必须使用index.ftl 在其中运行的相同 Environment,而不是新的(使用Environment.getCurrentEnvironment())。主要是为了得到相同的数据模型。而且您真的不应该为每个模板处理重新创建Configuration...您每次都会丢失模板缓存。我再次警告您,解决这个问题可能是深水,您必须了解 FM,甚至可能修补视图 servlet。这不是一个已解决的问题。
  • 顺便说一句,如果你成功与主模板共享环境,那么下一个问题将是现在标签模板没有自己的变量命名空间,所以它们会在共享命名空间中乱七八糟,破坏每个其他变量,这显然是不可接受的。这就是 FreeMarker 通过 #import 进行命名空间的原因,但您在这里没有使用 #import,所以...它可能还需要修补 FM,因此您可以在不使用 #import 的情况下做到这一点。
【解决方案2】:

我终于能够解决这个问题。感谢@ddekanny 和我的同事为您指明方向。

将我的模板添加到由 FreemarkerServlet 创建的当前环境解决了我的问题。

Environment currentEnvironment = Environment.getCurrentEnvironment();
Configuration cfg = currentEnvironment.getTemplate().getConfiguration();

cfg.setClassForTemplateLoading(this.getClass(), "/");

Template ftlTemplate = cfg.getTemplate(view);
JspWriter writer = pageContext.getOut();

currentEnvironment.setVariable("this", new SimpleHash(data));
currentEnvironment.setOut(writer);
currentEnvironment.include(ftlTemplate);

【讨论】:

    猜你喜欢
    • 2011-12-27
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    相关资源
    最近更新 更多