当FreeMarker遇到正则表达式
需求描述
在编制 FreeMarker 模板文件时,我有一个需求,简单描述如下:
将一个表达式(expr)进行分解成多个token,每个token要么是一个标识符、要么不是,比如
当 expr = "name" 时,只包含一个token,即 ["name"];
当 expr = "name||name2" 时,可分解成3个token,即 ["name", "||", "name2"];
当 expr 就是一个 token 时,有一些特殊处理。
有问题的实现
于是,在 ftl 文件中,这样写道:
-
<#macroparseExpr1expr>
-
parse${expr}
-
<#assigntokens=expr?matches("[\\w]+|[^\\w]+")/>
-
<#listtokensastoken>
-
<#iftokens?size==1>
-
[${token}]
-
<#else>
-
[${token}]
-
</#if>
-
</#list>
-
</#macro>
-
-
<@parseExpr1expr="name"/>
-
<@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)
如果注释掉第二个测试,就不会有问题。
-
<@parseExpr1expr="name"/>
-
<#--<@parseExpr1expr="name||name2"/>-->
parse name
[name]
也就是说,在 expr 能分解成多个 token 时,这种写法就会有问题。
无问题的实现
上面 tokens?size 是在循环中计算的,改成在循环外计算试试:
-
<#macroparseExpr2expr>
-
parse${expr}
-
<#assigntokens=expr?matches("[\\w]+|[^\\w]+"),count=tokens?size/>
-
<#listtokensastoken>
-
<#ifcount==1>
-
[${token}]
-
<#else>
-
[${token}]
-
</#if>
-
</#list>
-
</#macro>
-
-
<@parseExpr2expr="name"/>
-
<@parseExpr2expr="name||name2"/>
输出结果如下:
parse name
[name]
parse name||name2
[name]
[||]
[name2]
这样就没有问题了。从逻辑上讲,两个实现其实是等同的。这应该是 FreeMarker 在处理正则表达式的时候出现了问题。
测试用的 java 代码
-
importfreemarker.template.*;
-
importjava.util.*;
-
importjava.io.*;
-
-
publicclassTest{
-
-
publicstaticvoidmain(String[]args)throwsException{
-
-
-
-
-
-
Configurationcfg=newConfiguration();
-
cfg.setDirectoryForTemplateLoading(newFile("templates"));
-
cfg.setObjectWrapper(newDefaultObjectWrapper());
-
-
-
-
-
-
Templatetemp=cfg.getTemplate("test.ftl");
-
-
-
Maproot=newHashMap();
-
-
-
Writerout=newOutputStreamWriter(System.out);
-
temp.process(root,out);
-
out.flush();
-
}
-
-
}
分享到:
相关推荐
在实际开发中,除了直接使用正则表达式替换模板,还可以使用模板引擎库,如FreeMarker、Velocity或Thymeleaf等,它们提供了更高级的功能,如变量绑定、控制结构和函数调用,适合于生成动态HTML或其他格式的文档。...
5. **模板引擎**:一些模板引擎如FreeMarker或Velocity,它们的配置或模板语法中也支持正则表达式,用于动态内容的处理。 这个压缩包很可能包含JSP的基本教程、实例代码、正则表达式的使用指南,甚至可能有实战项目...
我们将深入探讨每个方面,同时引入正则表达式在验证用户输入中的应用。 首先,让我们看看"新浪微博邮箱登录界面"。这个界面通常会包含用户名(可以是手机号或邮箱)输入框、密码输入框、登录按钮,以及可能的记住...
`replaceAll` 方法会查找所有与正则表达式匹配的部分,并用提供的字符串替换它们。 6. 最后,返回处理后的字符串 `content`。 在测试案例中,我们创建了一个字符串 `content`,其中包含了两个占位符 `${name}` 和 ...
FreeMarker使用${...}表达式来插入变量,#{...}用于输出注释,以及、等控制结构进行条件判断和循环。然而,这些默认标签可能无法满足所有复杂的场景,因此自定义标签就显得尤为必要。 自定义FreeMarker标签通常涉及...
在探讨如何用JavaScript编写一个只删除所有font标签的正则函数之前,我们首先需要了解font标签和正则表达式的基础知识。 font标签是HTML早期用来定义字体样式、大小和颜色的一个元素。例如,`文字内容</font>`。...
解析过程涉及正则表达式、词法分析和语法分析等技术。 2. **数据模型与模板结合**:Freemarker的数据模型可以是任何Java对象,它将对象映射到模板中的变量。开发者可以通过`ModelFactory`将业务数据绑定到模板,...
### Struts 结合 JS 的表单验证 在 Web 开发中,前端表单验证是非常重要的一个环节,它能够有效提高用户...同时,利用 JavaScript 的正则表达式功能,还可以方便地完成各种格式校验任务,从而提高应用程序的整体质量。
Freemarker支持丰富的表达式,如`${user.name}`用来获取user对象的name属性,`<@util.formatDate date='yyyy-MM-dd'/>`调用自定义宏进行日期格式化。 8. **控制结构** Freemarker提供了条件语句(`<#if>`, `...
1. **基础概念**:Freemarker的工作原理,模板语言的基础元素,如变量、表达式、控制结构(if/else、foreach)以及注释等。 2. **数据模型**:理解如何将Java对象绑定到模板,包括基本类型、集合、Map等数据结构的...
它可能负责读取模板文件,使用正则表达式替换特定内容,然后利用反射操作和文件写入功能,将处理后的数据写入新的文件中。 总结来说,这个项目涉及了Java开发中的基础操作和高级特性,包括文件的读写、路径处理、...
4. **表达式**:FreeMarker支持丰富的表达式语法,包括算术表达式、比较表达式、逻辑表达式以及对对象方法的调用,这使得在模板中进行复杂的数据处理成为可能。 5. **缓存机制**:FreeMarker有内置的缓存系统,可以...
如果在Eclipse中使用,可以将该JAR文件添加到项目的构建路径,确保项目能正确识别并利用Freemarker的功能。在"freemarker2.3.28"这个压缩包中,可能包含了Freemarker的完整源代码、文档、示例和其他相关资源,便于...
- 注释:`#comment`,在模板中插入注释,不会出现在生成的输出中。 - 控制结构:`#if`、`#else`、`#foreach`等,用于条件判断和循环。 - 范围:`#set`,设置变量。 - 包含:`#include`,嵌入其他模板。 3. **...
例如,如果项目对性能有较高要求,可能会倾向于选择较新版本,因为它们通常包含性能优化。同时,也要注意与现有项目依赖库的兼容性,确保版本升级不会引发冲突。在升级过程中,需要充分测试以确保所有功能正常运行,...
`freemarker-2.3.23.jar`是Freemarker库的一个版本,发布于2.3.23,这个版本可能包含了对早期版本的一些改进、新功能或bug修复。 Freemarker的核心概念是模板语言,它是一种声明式的编程方式,允许开发者编写不包含...
例如,`<#if user.isAdmin>` 和 `${user.name}` 是常见的FreeMarker指令和变量表达式。 2. **数据模型**:这是FreeMarker渲染模板时所用到的数据,通常由应用程序提供。它可以是Java对象、Map、List等,用于填充...
1. **变量和表达式**:在FreeMarker模板中,`${}`内的内容是表达式,用于获取Java对象的属性或执行简单的运算。例如`${user.name}`将输出用户对象的name属性。 2. **指令**:FreeMarker提供了一系列的内置指令,如`...
- Freemarker支持变量、表达式、控制结构、函数和宏等高级功能。 - 变量表达式 `${variable}` 输出变量值,`<#assign>` 定义变量,`<#if>`、`<#else>`、`<#foreach>` 控制流程。 - 功能如日期格式化、条件判断、...
Freemarker-IDE是一款专为开发人员设计的Eclipse插件,它主要针对Freemarker模板语言提供了强大的支持。在Eclipse这样的集成开发环境中,这款插件...如果你在日常工作中经常与Freemarker打交道,这个插件绝对值得尝试。