`name` 作为 freemarker 中断中的变量名

Posted

技术标签:

【中文标题】`name` 作为 freemarker 中断中的变量名【英文标题】:`name` as a variable name in freemarker breaks 【发布时间】:2015-03-26 13:22:05 【问题描述】:

我在 ftl 中有以下代码:

<#macro field label name value="" type="text">
    $name
    $name!"print if null"
    <div class="field">
        <div class="clearfix" id="$name_field">
            <label for="$name">$label</label>
            <div class="input">
            <input type="$type" id="$name" name="$name" value="$value">
                <span class="help-inline"></span>
                <span class="help-block"></span> 
            </div>
        </div>
    </div>
</#macro>


<@field label="label" name="test" />

这是打印这个:

foo-test
test
<div class="field">
    <div class="clearfix" id="foo-test_field">
        <label for="foo-test">label</label>
        <div class="input">
        <input type="text" id="foo-test" name="foo-test" value="">
            <span class="help-inline"></span>
            <span class="help-block"></span> 
        </div>
    </div>
</div>

foo-test 是我的应用程序的名称,但不明白为什么它会打印在那里.. 刚刚使用 ctrl+f 搜索foo-test,它在 ftl 或控制器中无处...

除此之外,让我们假设name 是一个具有我的应用程序名称的变量。那么为什么第二个打印只打印我传递给我的宏的正确值?这真的很奇怪……

我使用 Maven 和 spark,所以我有这个依赖:

    <dependency>
        <groupId>com.sparkjava</groupId>
        <artifactId>spark-template-freemarker</artifactId>
        <version>2.0.0</version>
    </dependency>

插件是这样的:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources> 
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.1</version>
            <configuration>
                <mainClass>com.example.foo.foo-test</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

我的控制器看起来像这样:

    .....

    import spark.ModelAndView;
    import spark.Spark;
    import spark.template.freemarker.FreeMarkerEngine;

    ......

    Spark.get("/foo", (request, response) -> 
        Map<String, Object> attributes = new HashMap<>();
        return new ModelAndView(attributes, "test.ftl");
    , new FreeMarkerEngine());

【问题讨论】:

你在用maven吗? @AleksandrM 是的,这与此有关吗? 你如何在 maven 中打包/包含你的 ftl-s?你能显示你的 pom.xml 吗? @AleksandrM 我刚刚用信息更新了问题 显示你的 pom plugins 部分。 【参考方案1】:

发生这种情况是因为您已将 maven 配置为过滤资源,它确实将 $name 占位符替换为您的项目名称。

从您的 pom 中删除 &lt;resources&gt;,或者如果您确实需要资源过滤,您可以排除 ftl-s 文件。

<resources>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
    </resource>
</resources>

顺便说一句,关于resource filtering 的maven-resources-plugin 文档使用$name 占位符演示了这种行为。 :)

【讨论】:

就是这样!不敢相信 Maven 正在这样做..并且无法理解为什么只发生在宏内部..谢谢!!【参考方案2】:

很奇怪......它应该可以工作,并且对我有用。我怀疑在 FreeMarker 解析它之前,在该模板中搜索并替换了 $name (例如,自定义 TemplateLoader-s 可以做到这一点)。比如,如果你写 $name&lt;#-- just a comment --&gt; 而不是 $name 会发生什么?

【讨论】:

你是对的。如果我写$name&lt;#-- just a comment --&gt;,那么它会打印出我想要的内容。但是如果只在第一行打印$name,它会抛出一个错误,即名称未定义。为什么这只发生在宏内部?? 我不知道在 FreeMarker 得到它之前对模板文件应用了什么魔法......你能做一个System.out.println(template) 其中templatefremarker.template.Template 对象来看看里面有什么模板?另外,那是什么 FreeMarker 版本($.version)?我希望不是 10 年前的预览版...... 或者更确切地说,System.out.println(template.getSource()) 版本打印2.3.19,对于模板,我不知道从哪里获得模板,因为它嵌入在 spark-template-freemarker 中.. 2.3.19 是一个过时但稳定的版本,所以这不是问题。至于如何获取Template 对象,您可以做一个hack:实现TemplateDirectiveModel,然后您可以从env.getTemplate() 获取它(至少如果它是***模板),并打印结果到env.getOut()Writer。然后在模板中调用这个指令,如&lt;@'com.example.YourDirective'?new() /&gt;

以上是关于`name` 作为 freemarker 中断中的变量名的主要内容,如果未能解决你的问题,请参考以下文章

freemarker模板中的日期格式问题

关于FreeMarker的list循环取值问题

freemarker莫名报错

Freemarker判断是否为空

如何获得可重复的文本字段 liferay7 Freemarker 之一

freemarker中表达式 $(user.name)!""当user为空时,直接报错,咋回事?