前两天,周末在家无事,想起以前的项目是基于struts2开发的,而在struts2中又大量运用了freemarker,所以就想也去试用下freemarker。
在struts2的guide文章中,说明了为什么要使用freemarker的理由。
The framework utilizes FreeMarker because the engine includes strong error reporting,
built-in internationalization and powerful macro libraries.
即准确的错误地方以及内置的国际化处理以及强大的自定义宏处理。
从网上下载了一个简单的freemarker中文文档以及官方的手册,简单看了下,然后开始处理中。首先根据每个界面都需要引用相同的html代码以及结尾处理。写了一个简单的html.ftl信息,然后在每个界面都包含进来。如下
<#assign g=JspTaglibs["/WEB-INF/gtip.tld"] />
<#macro body title="标题">
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
<#include "header.ftl" />
</head>
<body>
<#nested />
</body>
</html>
</#macro>
就是简单的一个宏处理,以及声明包含一个自定义的jsptag信息,将title信息写进head中的title标签,然后引用公共使用的header.ftl(即相应的js以及css),最后在body标签中调用相应的代码信息。
这样在其他界面中,只需要<#include "html.ftl"/>,然后再调用<@body>这个宏即可。
接下来,就是将每个界面的jsp修改为ftl了,除了在struts.xml中修改每个result的type为freemarker之外,还需要将每个jsp重新copy成ftl,然后进行改造。
对于每个ftl,首先将原来的<s:调用方式,修改为freemarker的<@s.的调用方式。如<s:iterator>修改为<@s.iterator>这样的形式。我使用了一个正则表达式来进行字符替换,使用 (?<=<(?:/)?)(\w): 来匹配相应的标签,并使用 @\$1. 来替换掉。上面的字符会匹配<s:iterator中的<s:,也可以匹配</s:iterator中的</s:,直接将其替换即可。
其次,将其中的<s:property value="XX"/>的形式(经第一步之后,变成了<@s.property value="XX"/>了),修改为${xxx}的形式。因为使用freemarker嘛,所以要修改过来。这里也使用了一个正则表达式进行替换,由 <@s.property value="#?([\w\.]+)"/> 替换为 \\$\{\$1} ,即可实现这个修改。
接下来修改其他标签。
将<@s.iteraotr标签,修改为<#list >的形式;
将<@s.if></@s.if><@s.else>修改为<#if><#else>的形式。
花了近一天的时候,终于将相应的界面修改了。最后重新启动工程进行运行,结果出问题了。问题有以下几个:
1,如果ftl界面不能完全解析,则相应的界面将完全以源代码的形式显示在界面上。
这个问题,由于比如其中的某些type没有正则的匹配相应的ftl,而后台以dispatcher的形式返回回来之后,界面就直接将整个ftl文件完整地显示在界面上了。这样对于文件的保护,而且对于开发来说都是不大好的。
2,首页以及登陆界面的问题。
如果将首页以及相应的前台界面修改为ftl的形式,那么在进行访问的时候就必须以非ftl的形式进行访问了,如通过xxx.do的形式进行访问,这样还必须给相应的ftl文件追加相应的action匹配。如原来的login.jsp,现在就必须以login.do进行访问,而且需要给这个映射追加一个action映射信息。如果前面界面有很多,面分散在不同的目录中,那么就需要有多个不同的匹配来进行, 这样无凝增加了无谓的工作。
当然有一个解决办法就是保存前台界面为jsp不变,但又出现新的问题,即当前台界面引用其他界面时,又会出现相同的问题。即其他界面均修改为ftl,而ftl中有相应的freemarker解析标签。如login.jsp引用error.ftl时,将会出现error.ftl中的信息不能被解析的问题。当然可以保存error.ftl和error.jsp同时存在。但这样就失去了freemarker的作用了。
3,最重要的,toString问题和null问题以及map问题
3.1 freemarker没有对list以及map结构有一个很好的toString支持,即直接调用${x}时,如果x为一个list时,将直接显示一个List@xxx的形式。这样,就要求我们必须为其编写一个sequenceToString的macro,而且还需要在调用中对x的类型进行判断(通过?_isXXX的形式),再进行相应的处理。
3.2 map问题,即freemarker中不能支持非string的key值,这样在进行一些复杂迭代时就需要作一些其他的转换,如将一个map拆分为两个或多个map。
3.3 三元运算符的支持。由于缺少三元运行符,所以在一些复杂的判断中,为一个变量进行赋值时,就需要用多个<#if和<#else>进行处理。本来只需要一个三元运算就能解决的问题,由用<#if和<#else>就需要写很长一段代码。
3.4 null问题。这是最重要的,freemarker没有一个默认的null处理,甚至也不接受一个null值。如x=null(X变量是存在的),打印${x}时,将直接报一个错误,而不是打印类似的""值或null等。这样在进行很多显示中,都需要在相应的变量后面加一个!,如${x!}这样的形式,很是麻烦。
在<#list中,也需要使用类似<#if (list)!>的形式。而由于缺少对null的支持,需要写一个类似x==null这样的判断时,就需要写成!(x??)的特殊形式,而且到处均需要写成(XX?method?method)?或!的形式以进行null的处理。
导致我决定不使用freemarker的原因,就是现阶段没有发现其比struts2标签更方便。尤其在对于null的处理上,ognl标签相比来说更容易使用,当碰到出现类似nullPointer的时候,struts2标签在处理时将直接采用默认的处理方式,如显示为""(对于iterator或if时,将直接返回false,以结束迭代或判断)。这样就不需要开发人员再去进行无谓的null处理,而这个结果正是在web开发中所需要的。
网上再找了下,freemarker对于一些模板文件的生成还是很有用的,比如在项目中,就依照struts2的标签开发用freemarker生成一个tree树,再采用标签进行封装来调用。如下所示:
<#-- 写一个子集列表 -->
<#macro writeOne node expand>
<li>
<input type="checkbox" name="${node.nameParam}" value="${node.id}"
<#if node.checked>
checked="checked"
</#if>
/>
<span>${node.name}</span>
<#if expand && (node.childList?? && node.childList?size > 0)>
<ul>
<@write nodeList=node.childList expand=expand/>
</ul>
</#if>
</li>
</#macro>
<#-- 写上级结点 -->
<#macro write nodeList expand>
<#list nodeList as node>
<@writeOne node=node expand=expand/>
</#list>
</#macro>
<@write nodeList=parameters.nodeList expand=parameters.expand/>
最后决定,在进行jsp开发上,还是使用jsp+struts2标签进行开发,而使用一些模板文件生成的时候,或许可以考虑一下freemarker。至少对于我来说,freemarker已经没有那么大的吸引力了。
分享到:
相关推荐
本篇将深入探讨如何自定义FreeMarker标签,以扩展其功能并适应特定项目需求。 首先,理解FreeMarker的默认标签语法至关重要。FreeMarker使用${...}表达式来插入变量,#{...}用于输出注释,以及、等控制结构进行条件...
在Java应用中,Freemarker通过ModelAndView或者Map对象将数据传递到视图层。开发者可以在Java后端准备数据模型,然后传递给Freemarker模板,模板根据模型中的数据生成HTML输出。 4. **与Struts2集成** Struts2是...
在提供的代码片段中,`FreemarkerUtil`类封装了Freemarker的基本操作,包括模板的获取、数据模型的处理以及输出到流或文件。其中`getTemplate`方法负责模板的加载,而`print`和`fprint`方法分别用于输出到控制台和...
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-2.3.23.jar`是Freemarker库的一个版本,发布于2.3.23,这个版本可能包含了对早期版本的一些改进、新功能或bug修复。 Freemarker的核心概念是模板语言,它是一种声明式的编程方式,允许开发者编写不包含...
版本号"0.9.14"表示这是该插件的一个具体版本,用户可以根据实际需求选择安装相应版本,或者升级到最新版本以获取更多改进和新功能。 总的来说,"eclipse的freemarker插件"是Eclipse开发环境中不可或缺的工具之一,...
1. **安装与配置**:FreeMarker是一个轻量级库,可以通过Maven或Gradle等构建工具引入到Java项目中。配置主要涉及设置模板目录和配置文件`freemarker.properties`,其中定义了FreeMarker的行为,例如模板的缓存策略...
在实际应用中,开发者通常会将这个JAR文件添加到项目的类路径(classpath)中,以便在运行时能够解析和执行Freemarker模板。如果在Eclipse中使用,可以将该JAR文件添加到项目的构建路径,确保项目能正确识别并利用...
FreeMarker 2.3.18是该引擎的一个版本,它提供了一系列的更新和改进,以提高性能和易用性。 1. **模板语言基础** FreeMarker的模板语言是一种声明式的编程方式,它允许开发者通过简单的标记语法来控制输出。这些...
总的来说,这个压缩包提供了一套完整的Freemarker学习资源,从基本的API文档到开发环境的集成工具,再到源码级别的深入研究。无论是初学者还是有经验的开发者,都可以从中找到自己需要的信息,提升对Freemarker的...
赠送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文档:...
赠送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文档:...
1. **变量与表达式**:在FreeMarker模板中, `${variable}` 用于表示变量,它会从数据模型中查找对应的值并输出。表达式支持算术运算、比较运算和逻辑运算,例如 `${a + b}`、`${c > d}` 和 `${e && f}`。 2. **...
2.3.23是FreeMarker的一个稳定版本,这个版本的官方中文文档提供了全面的指导和说明,帮助开发者更好地理解和使用这个模板语言。 在FreeMarker的核心概念中,它是一个基于数据驱动的模板语言。这意味着,开发者不...
在这个"freemarkerdemo生成word插入图片"的示例中,我们主要探讨如何利用Freemarker来创建Word文档,并且将图片集成到这些文档中。这个过程涉及到几个关键的技术点: 1. **Freemarker基础知识**:Freemarker是一个...
"freemarker编辑插件"能够集成到Eclipse中,使得开发者在编写Freemarker模板时可以享受到诸如语法高亮、自动完成、错误检查等功能。这个插件的版本为0.9.14,可能包含了对Freemarker语法的最新支持以及一些优化的...
freemarker替换变量实例
再者,从语法格式上来讲,Velocity 和 Freemarker 的语法格式不同,Velocity 的语法更加简洁,而 Freemarker 的语法更加灵活。不同的开发者可能会有不同的倾向性,但是Freemarker 的语法更加强大。 最后,从性能上...
如果当前页小于等于一半显示页数,则显示从第一页开始的页码;反之,显示以当前页为中心的页码。 - **分段显示页码**:根据当前页和总页数,分两段显示页码。首先显示前半部分,然后是后半部分。这确保了用户界面的...