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

无法访问Freemarker中的嵌套Jsp标记,jsp,jsp-tags,freemarker,Jsp,Jsp Tags,Freemarker,我已经使用freemarker作为视图模板编写了一个Jsp标记库 custom.tld放在META-INF/tags/中 我的标签库被捆绑成JarcustomTag.jar。 它有以下模板 AlertTag.ftl ButtonTag.ftl AlertTag.ftl取决于ButtonTag.ftl AlertTag.ftl:- <#assign custom = JspTaglibs["http://www.abc.com/taglibs/custom"]> <h5>

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

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>
<taglib>
   <taglib-uri>http://www.abc.com/taglibs/custom</taglib-uri>
   <taglib-location>/WEB-INF/custom.tld</taglib-location>
</taglib>
现在,当web应用程序中的
index.ftl
尝试使用标记
时,会引发以下异常

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);
Configuration cfg=新配置();
setClassForTemplateLoading(this.getClass(),“/”;
模板ftlTemplate=cfg.getTemplate(视图);
JspWriter writer=pageContext.getOut();
data.put(“id”,id)
Map rootMap=newhashmap();
rootMap.put(“this”,数据);
Environment=ftlTemplate.createProcessingEnvironment(rootMap,writer);
过程();
//ftlTemplate.process(rootMap,writer);

@丹尼尔,我用过上面的环境,但也不起作用。我是否正确地使用了它?

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

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


事实是,FreeMarker的设计目的是使用它自己的宏/指令/函数功能来创建库。一些开发人员有这样的想法,自定义JSP标记可以像FreeMarker指令一样公开。。。如果您试图迁移到FTL视图,但有很多JSP标记库,那么这是一个有用的黑客攻击,FreemarkerSerlvet本身就是为了帮助您在“JSP模型2”框架内迁移而添加的(一个模型本身就是一个相当笨拙的黑客攻击,它迫使JSP上使用MVC)。如果您将JSP支持扩展到这个范围之外。。。现在,你必须深入挖掘的可能性很高。

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

如何调用
AlertTag.ftl
本身?我是从web应用程序中的index.ftl调用它的
I
假设@custom.Alert
本身是一个自定义JSP标记,而不是普通的FreeMarker宏/指令。因此,我的意思是如何从技术上调用
AlertTag.ftl
。因为我怀疑JSP标记将创建自己的FreeMarker引擎实例,该实例与
index.ftl
所使用的实例无关,因此,如果存在JSP taglib支持,则all.yes、@custom.Alert是一个自定义JSP标记。我编写了一个AlertTag.java文件,该文件在custom.tld中定义。在AlertTag.java中,我调用了AlertTag.ftl。让我把它添加到问题中。我已经对问题进行了编辑,并按照您所说的使用了环境变量。请参见上面的编辑,但id不起作用。我不太确定我是否正确使用了它。您必须使用与运行
index.ftl
环境相同的
环境,而不是新环境(使用
Environment.getCurrentEnvironment()
)。主要是为了得到相同的数据模型。而且您确实不应该为每个模板处理重新创建
配置
。。。每次都会丢失模板缓存。我再次警告您,解决这一问题可能需要深入研究,您必须了解FM,甚至可能需要修补ViewServlet。这不是一个已解决的问题。顺便说一句,如果您成功地与主模板共享环境,那么下一个问题将是,现在标记模板没有自己的变量名称空间,因此它们将在共享名称空间中混乱,相互碰撞变量,这显然是不可接受的。这就是为什么FreeMarker通过
#import
使用名称空间,但您没有在此处使用
#import
,因此。。。它可能还需要对FM进行修补,因此您无需导入即可完成。