无法访问Freemarker中的嵌套Jsp标记

时间:2013-06-16 18:14:33

标签: jsp jsp-tags freemarker

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

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

我的标签Lib被捆绑为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尝试使用标记<@custom.Alert id="abc">时,它会抛出以下异常

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,我已经使用了上面的环境,但它也没有用。我正确使用它吗?

2 个答案:

答案 0 :(得分:1)

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

因此,当您在AlterTag.java中创建自己的FreeMarker引擎并拥有自己的数据模型时,就会切断所有这些。您是否尝试设置类似的数据模型(我不知道是否有人设法将其与FreemarkerServlet ...分开),或者您必须在freemarker.core.Environment中运行模板index.ftl使用的{。}}。您可以使用Environment.getCurrentEnvironment()从TLS获取当前环境,然后您可以使用Environment方法来包含模板,假设模板加载器可以访问该模板。所以你没有自己的数据模型......相当混乱。

事实上,FreeMarker旨在使用自己的宏/指令/功能来创建库。一些开发人员认为自定义JSP标记可以像FreeMarker指令一样公开...如果你试图迁移到FTL视图但是你有很多JSP标记库,那么这是一个有用的黑客,所以FreemarkerSerlvet,本身被添加以帮助您在“JSP Model 2”框架内迁移(这个模型本身是一个非常难以在JSP上强制MVC的黑客攻击)。如果你现在将JSP支持扩展到那个......那么你很可能需要深入研究。

答案 1 :(得分:0)

我终于能够解决这个问题了。感谢@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);