`
coding1688
  • 浏览: 232727 次
  • 来自: 上海
社区版块
存档分类
最新评论

当FreeMarker遇到正则表达式,Bug就出现了

 
阅读更多

当FreeMarker遇到正则表达式

需求描述

在编制 FreeMarker 模板文件时,我有一个需求,简单描述如下:

将一个表达式(expr)进行分解成多个token,每个token要么是一个标识符、要么不是,比如

当 expr = "name" 时,只包含一个token,即 ["name"];

当 expr = "name||name2" 时,可分解成3个token,即 ["name", "||", "name2"];

当 expr 就是一个 token 时,有一些特殊处理。

 

有问题的实现

于是,在 ftl 文件中,这样写道:

 

 

<#macro parseExpr1 expr>
        parse ${expr}
        <#assign tokens = expr?matches("[\\w]+|[^\\w]+")/>
        <#list tokens as token>
                <#if tokens?size == 1>
                        [${token}]
                <#else>
                        [${token}]
                </#if>
        </#list>
</#macro>

<@parseExpr1 expr="name"/>
<@parseExpr1 expr="name||name2"/>

 

 

上面的代码在执行时会有异常抛出:

Exception in thread "main" java.lang.IllegalStateException: No match available

        at java.util.regex.Matcher.start(Matcher.java:325)

        at freemarker.core.RegexBuiltins$RegexMatchModel$Match.<init>(RegexBuiltins.java:350)

        at freemarker.core.RegexBuiltins$RegexMatchModel$2.next(RegexBuiltins.java:339)

        at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:164)

        at freemarker.core.Environment.visit(Environment.java:428)

        at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)

        at freemarker.core.Environment.visit(Environment.java:221)

        at freemarker.core.MixedContent.accept(MixedContent.java:92)

        at freemarker.core.Environment.visit(Environment.java:221)

        at freemarker.core.Macro$Context.runMacro(Macro.java:172)

        at freemarker.core.Environment.visit(Environment.java:614)

        at freemarker.core.UnifiedCall.accept(UnifiedCall.java:106)

        at freemarker.core.Environment.visit(Environment.java:221)

        at freemarker.core.MixedContent.accept(MixedContent.java:92)

        at freemarker.core.Environment.visit(Environment.java:221)

        at freemarker.core.Environment.process(Environment.java:199)

        at freemarker.template.Template.process(Template.java:259)

        at Test.main(Test.java:28) 

 

如果注释掉第二个测试,就不会有问题。

 

 

<@parseExpr1 expr="name"/>
<#-- <@parseExpr1 expr="name||name2"/> -->

 

        parse name

                        [name]

 

 

也就是说,在 expr 能分解成多个 token 时,这种写法就会有问题。

 

无问题的实现

上面 tokens?size 是在循环中计算的,改成在循环外计算试试:

 

 

<#macro parseExpr2 expr>
        parse ${expr}
        <#assign tokens = expr?matches("[\\w]+|[^\\w]+"), count = tokens?size/>
        <#list tokens as token>
                <#if count == 1>
                        [${token}]
                <#else>
                        [${token}]
                </#if>
        </#list>
</#macro>

<@parseExpr2 expr="name"/>
<@parseExpr2 expr="name||name2"/>

 

 

 

输出结果如下:

        parse name

                        [name]

        parse name||name2

                        [name]

                        [||]

                        [name2]

 

 

这样就没有问题了。从逻辑上讲,两个实现其实是等同的。这应该是 FreeMarker 在处理正则表达式的时候出现了问题。

 

测试用的 java 代码

 

import freemarker.template.*;
import java.util.*;
import java.io.*;
        
public class Test {
                        
        public static void main(String[] args) throws Exception {
                        
                /* ------------------------------------------------------------------- */
                /* You should do this ONLY ONCE in the whole application life-cycle:   */
    
                /* Create and adjust the configuration */
                Configuration cfg = new Configuration();
                cfg.setDirectoryForTemplateLoading(new File("templates"));
                cfg.setObjectWrapper(new DefaultObjectWrapper()); 
        
                /* ------------------------------------------------------------------- */
                /* You usually do these for many times in the application life-cycle:  */
                
                /* Get or create a template */
                Template temp = cfg.getTemplate("test.ftl");
        
                /* Create a data-model */
                Map root = new HashMap();

                /* Merge data-model with template */
                Writer out = new OutputStreamWriter(System.out);
                temp.process(root, out);
                out.flush();
    }
        
}
 

 

 

3
0
分享到:
评论

相关推荐

    freemarker资料集

    FreeMarker语法之表达式,FreeMarker如何生成静态页面,freemarker空值的多种处理方法,FreeMarker的优点和缺点,Freemarker的内置函数及用法

    freemarker 自定义freeMarker标签

    NULL 博文链接:https://zhenghuazhi.iteye.com/blog/1923544

    安装freemarker插件(freemarker的eclipse插件)

    g) 退出Eclipse再重启,在window --&gt; Preferences 左边的树形栏里出现FreeMarker Editor一项新的内容。在General --&gt; Editors --&gt; File Associations下,为*.html和*.htm文件添加(add)FreeMarker Editor 作他们...

    freemarker-2.3.31-API文档-中文版.zip

    赠送jar包:freemarker-2.3.31.jar; 赠送原API文档:freemarker-2.3.31-javadoc.jar; 赠送源代码:freemarker-2.3.31-sources.jar; 赠送Maven依赖信息文件:freemarker-2.3.31.pom; 包含翻译后的API文档:...

    FreeMarker

    FreeMarker,FreeMarker

    freemarker-2.3.30-API文档-中文版.zip

    赠送jar包:freemarker-2.3.30.jar; 赠送原API文档:freemarker-2.3.30-javadoc.jar; 赠送源代码:freemarker-2.3.30-sources.jar; 赠送Maven依赖信息文件:freemarker-2.3.30.pom; 包含翻译后的API文档:...

    freemarker语法完整版

    Freemarker页面语法 A 概念 最常用的 3 个概念 sequence 序列,对应java 里的list 、数组等非键值对的集合 hash 键值对的集合 namespace 对一个ftl 文件的引用, 利用这个名字可以访问到该ftl 文件的资源 ...

    freemarker\Freemarker教程_中文版

    freemarker\Freemarker教程_中文版

    freemarker语法

    freemarker freemarker freemarker freemarker freemarker freemarker freemarker freemarker

    FreeMarker_Programmer Guide

    FreeMarker

    freemarker.jar

    camel-freemarker-1.6.4.jar, camel-freemarker-2.8.1.jar, com.springsource.freemarker-2.3.15.jar, com.springsource.freemarker-sources-2.3.15.jar, freemarker-1.4.1.jar, freemarker-2-3-18.jar, freemarker-...

    freemarker替换变量实例

    freemarker替换变量实例

    Freemarker 实例,Freemarker 实例

    Freemarker 实例,Freemarker 实例Freemarker 实例,Freemarker 实例

    freemaker模板教程

    FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等...

    FreeMarker中文文档.pdf下载

    FreeMarker中文文档.pdf FreeMarker入门必修

    FreeMarker手册-Freemarker 2.3.18

    FreeMarker手册-Freemarker 2.3.18。。。。。。。。。。。。。。。。。

    freemarker

    一篇freemarker很不错的文章 reeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:格式部分,不会输出 3,插值:即${...}或#{...}格式的部分,将使用...

    Freemarker模板生成pdf+java

    Freemarker模板生成pdf+javaFreemarker模板生成pdf+javaFreemarker模板生成pdf+javaFreemarker模板生成pdf+javaFreemarker模板生成pdf+java

    freemarker ftp编辑

    Preferences 左边的树形栏里出现FreeMarker Editor一项新的内容。在General --&gt; Editors --&gt; File Associations下,为*.html和*.htm文件添加(add)FreeMarker Editor 作他们关联的编辑器(associated ...

    eclipse的freemarker插件

    freemarker格式化的eclipse插件。用于freemarker的格式化。

Global site tag (gtag.js) - Google Analytics