`
kerlubasola
  • 浏览: 710024 次
文章分类
社区版块
存档分类
最新评论

FreeMarker如果遇到正则表达式的时候会出现的bug

 
阅读更多

当FreeMarker遇到正则表达式

需求描述

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

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

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

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

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

有问题的实现

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

Freemarker代码收藏代码
  1. <#macroparseExpr1expr>
  2. parse${expr}
  3. <#assigntokens=expr?matches("[\\w]+|[^\\w]+")/>
  4. <#listtokensastoken>
  5. <#iftokens?size==1>
  6. [${token}]
  7. <#else>
  8. [${token}]
  9. </#if>
  10. </#list>
  11. </#macro>
  12. <@parseExpr1expr="name"/>
  13. <@parseExpr1expr="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)

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

Freemarker代码收藏代码
  1. <@parseExpr1expr="name"/>
  2. <#--<@parseExpr1expr="name||name2"/>-->

parse name

[name]

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

无问题的实现

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

Freemarker代码收藏代码
  1. <#macroparseExpr2expr>
  2. parse${expr}
  3. <#assigntokens=expr?matches("[\\w]+|[^\\w]+"),count=tokens?size/>
  4. <#listtokensastoken>
  5. <#ifcount==1>
  6. [${token}]
  7. <#else>
  8. [${token}]
  9. </#if>
  10. </#list>
  11. </#macro>
  12. <@parseExpr2expr="name"/>
  13. <@parseExpr2expr="name||name2"/>

输出结果如下:

parse name

[name]

parse name||name2

[name]

[||]

[name2]

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

测试用的 java 代码

Java代码收藏代码
  1. importfreemarker.template.*;
  2. importjava.util.*;
  3. importjava.io.*;
  4. publicclassTest{
  5. publicstaticvoidmain(String[]args)throwsException{
  6. /*-------------------------------------------------------------------*/
  7. /*YoushoulddothisONLYONCEinthewholeapplicationlife-cycle:*/
  8. /*Createandadjusttheconfiguration*/
  9. Configurationcfg=newConfiguration();
  10. cfg.setDirectoryForTemplateLoading(newFile("templates"));
  11. cfg.setObjectWrapper(newDefaultObjectWrapper());
  12. /*-------------------------------------------------------------------*/
  13. /*Youusuallydotheseformanytimesintheapplicationlife-cycle:*/
  14. /*Getorcreateatemplate*/
  15. Templatetemp=cfg.getTemplate("test.ftl");
  16. /*Createadata-model*/
  17. Maproot=newHashMap();
  18. /*Mergedata-modelwithtemplate*/
  19. Writerout=newOutputStreamWriter(System.out);
  20. temp.process(root,out);
  21. out.flush();
  22. }
  23. }
分享到:
评论

相关推荐

    怎么利用Java正则表达式换模板

    在实际开发中,除了直接使用正则表达式替换模板,还可以使用模板引擎库,如FreeMarker、Velocity或Thymeleaf等,它们提供了更高级的功能,如变量绑定、控制结构和函数调用,适合于生成动态HTML或其他格式的文档。...

    jsp学习详细资料(含有正则表达式)

    5. **模板引擎**:一些模板引擎如FreeMarker或Velocity,它们的配置或模板语法中也支持正则表达式,用于动态内容的处理。 这个压缩包很可能包含JSP的基本教程、实例代码、正则表达式的使用指南,甚至可能有实战项目...

    javaweb新浪微博邮箱登录界面,图书周排行榜界面,正则表达式验证用户注册页面前端代码资源包

    我们将深入探讨每个方面,同时引入正则表达式在验证用户输入中的应用。 首先,让我们看看"新浪微博邮箱登录界面"。这个界面通常会包含用户名(可以是手机号或邮箱)输入框、密码输入框、登录按钮,以及可能的记住...

    Java用正则表达式实现${name}形式的字符串模板实例

    `replaceAll` 方法会查找所有与正则表达式匹配的部分,并用提供的字符串替换它们。 6. 最后,返回处理后的字符串 `content`。 在测试案例中,我们创建了一个字符串 `content`,其中包含了两个占位符 `${name}` 和 ...

    freemarker 自定义freeMarker标签

    FreeMarker使用${...}表达式来插入变量,#{...}用于输出注释,以及、等控制结构进行条件判断和循环。然而,这些默认标签可能无法满足所有复杂的场景,因此自定义标签就显得尤为必要。 自定义FreeMarker标签通常涉及...

    [js]一个只删除所有font标签的正则函数

    在探讨如何用JavaScript编写一个只删除所有font标签的正则函数之前,我们首先需要了解font标签和正则表达式的基础知识。 font标签是HTML早期用来定义字体样式、大小和颜色的一个元素。例如,`文字内容&lt;/font&gt;`。...

    freemarker源码.rar

    解析过程涉及正则表达式、词法分析和语法分析等技术。 2. **数据模型与模板结合**:Freemarker的数据模型可以是任何Java对象,它将对象映射到模板中的变量。开发者可以通过`ModelFactory`将业务数据绑定到模板,...

    struts结合js的表单验证

    ### Struts 结合 JS 的表单验证 在 Web 开发中,前端表单验证是非常重要的一个环节,它能够有效提高用户...同时,利用 JavaScript 的正则表达式功能,还可以方便地完成各种格式校验任务,从而提高应用程序的整体质量。

    freemarker Demo 适用于freemarker初学

    Freemarker支持丰富的表达式,如`${user.name}`用来获取user对象的name属性,`&lt;@util.formatDate date='yyyy-MM-dd'/&gt;`调用自定义宏进行日期格式化。 8. **控制结构** Freemarker提供了条件语句(`&lt;#if&gt;`, `...

    非常好的Freemarker中文教程

    1. **基础概念**:Freemarker的工作原理,模板语言的基础元素,如变量、表达式、控制结构(if/else、foreach)以及注释等。 2. **数据模型**:理解如何将Java对象绑定到模板,包括基本类型、集合、Map等数据结构的...

    文件写入,项目相对路径,java反射,模板数据写入

    它可能负责读取模板文件,使用正则表达式替换特定内容,然后利用反射操作和文件写入功能,将处理后的数据写入新的文件中。 总结来说,这个项目涉及了Java开发中的基础操作和高级特性,包括文件的读写、路径处理、...

    apache-freemarker-2.3.26

    4. **表达式**:FreeMarker支持丰富的表达式语法,包括算术表达式、比较表达式、逻辑表达式以及对对象方法的调用,这使得在模板中进行复杂的数据处理成为可能。 5. **缓存机制**:FreeMarker有内置的缓存系统,可以...

    freemarker-2.3.28.jar

    如果在Eclipse中使用,可以将该JAR文件添加到项目的构建路径,确保项目能正确识别并利用Freemarker的功能。在"freemarker2.3.28"这个压缩包中,可能包含了Freemarker的完整源代码、文档、示例和其他相关资源,便于...

    freemarker操作手册-完整freemarker教程

    - 注释:`#comment`,在模板中插入注释,不会出现在生成的输出中。 - 控制结构:`#if`、`#else`、`#foreach`等,用于条件判断和循环。 - 范围:`#set`,设置变量。 - 包含:`#include`,嵌入其他模板。 3. **...

    freemarker各种版本的jar包

    例如,如果项目对性能有较高要求,可能会倾向于选择较新版本,因为它们通常包含性能优化。同时,也要注意与现有项目依赖库的兼容性,确保版本升级不会引发冲突。在升级过程中,需要充分测试以确保所有功能正常运行,...

    freemarker-2.3.23jar

    `freemarker-2.3.23.jar`是Freemarker库的一个版本,发布于2.3.23,这个版本可能包含了对早期版本的一些改进、新功能或bug修复。 Freemarker的核心概念是模板语言,它是一种声明式的编程方式,允许开发者编写不包含...

    FreeMarker_2.3.23 中文

    例如,`&lt;#if user.isAdmin&gt;` 和 `${user.name}` 是常见的FreeMarker指令和变量表达式。 2. **数据模型**:这是FreeMarker渲染模板时所用到的数据,通常由应用程序提供。它可以是Java对象、Map、List等,用于填充...

    FreeMarker2.3.23官方中文文档

    1. **变量和表达式**:在FreeMarker模板中,`${}`内的内容是表达式,用于获取Java对象的属性或执行简单的运算。例如`${user.name}`将输出用户对象的name属性。 2. **指令**:FreeMarker提供了一系列的内置指令,如`...

    freemarker 简单项目示例

    - Freemarker支持变量、表达式、控制结构、函数和宏等高级功能。 - 变量表达式 `${variable}` 输出变量值,`&lt;#assign&gt;` 定义变量,`&lt;#if&gt;`、`&lt;#else&gt;`、`&lt;#foreach&gt;` 控制流程。 - 功能如日期格式化、条件判断、...

    freemarker-ide插件

    Freemarker-IDE是一款专为开发人员设计的Eclipse插件,它主要针对Freemarker模板语言提供了强大的支持。在Eclipse这样的集成开发环境中,这款插件...如果你在日常工作中经常与Freemarker打交道,这个插件绝对值得尝试。

Global site tag (gtag.js) - Google Analytics