模板技术在现代的软件开发中有着重要的地位,而目前最流行的两种模板技术恐怕要算freemarker和velocity了,webwork2.2对两者都有不错的支持,也就是说在webwork2中你可以随意选择使用freemarker或velocity作为view,模板技术作为view的好处是很多,尤其和jsp比较起来优点更大,众所周知jsp需要在第一次被执行的时候编译成servlet,那么这个过程是很慢的,当然很多应用服务器都提供预编译的功能,但是在开发的时候仍然给我们程序员带来了很多痛苦,每次修改都要多几秒钟,那在一天的开发中就有很多时间浪费在jsp的编译上了。用webwork in action的作者的话来说:“每次修改之后重新运行都要等等几秒是令人失望的,而频繁地修改jsp更是会令你的失望情绪变本加厉“。我们把模板技术引入到view中去可以带来更好的开发效率,而且模板的速度要比jsp快(虽然编译过后的jsp在速度上已经满足我的需求了,呵呵)。 当然模板技术可以用在很多领域,可不只在view那里。我们可以通过模板技术来生成xml,生成jsp,生成java文件等等,说到这里,大家通常会使用模板技术用在公司的框架里,这样就可以很快速的生成添删改查的代码,需要的只是模板,其他比如还有邮件模板等等。
以上是模板的作用,那么现在开源的模板技术有好几种,多了之后就有一个选择的问题了,如何选择一个满足自己需要的模板的呢,写了一个例子,我使用了几种设计模式来完成了这个例子,这个例子中,同时使用了freemarker和velocity,这样同学们可以通过代码很直观的比较两种模板技术,通过这个例子,我认识到freemarker在功能上要比velocity强大
1。在view层的时候,它提供了format日期和数字的功能,我想大家都有在页面上format日期或数字的经验,用jsp的同学可能对jstl的fmt标签很有感情,使用了freemarker之后也可以使用freemarker提供的功能来formmat日期和数据,这个功能我想是很贴心的
2。通过我的使用我发现freemaker的eclipseplugin要比velocity的eclipseplugin好,好在很多地方呢,freemarker的插件除了支持freemarker语法也支持html语句,而velocity的插件貌似只支持velocity的语法,html就只是用普通的文本来显示了,在这一点上freemarker占上风了
3。freemarker对jsptag的支持很好,算了,不到迫不得已还是不要这样做吧。
jsp的第一次运行,就要运行servlet,如果开发时频繁的修改jsp,会导致开发速度比较慢;(每改一次,要重新编译一次);
编译过后,模板的速度也要比jsp快.
具体的freemark页面上的使用:见http://blog.csdn.net/nengyu/article/details/6829244
最近做的项目中要在spring mvc中实现freemark 加载html模板,关键实现如下:
第一步:引入freemark.jar包
第二步:web.xml中的配置
<!-- freemarker 配置 --> <bean id="freeMarkerConfigurer" class="com.test.common.freemarker.CustomFreeMarkerConfigurer"> <!--freemark的配置文件类--> <property name="templateLoaderPaths"> <list> <value>/WEB-INF/template/</value> <!--html文件的存放位置--> </list> </property> <property name="freemarkerSettings"> <props> <prop key="template_update_delay">5</prop> <prop key="default_encoding">UTF-8</prop> <prop key="locale">zh_CN</prop> <prop key="url_escaping_charset">UTF-8</prop> <prop key="date_format">yyyy-MM-dd</prop> <prop key="time_format">HH:mm:ss</prop> <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop> <prop key="number_format">0.######</prop> <prop key="boolean_format">true,false</prop> <prop key="classic_compatible">true</prop> <prop key="whitespace_stripping">true</prop> </props> </property> </bean> <!-- freemark 页面解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> <property name="contentType" value="text/html; charset=utf-8" /> <property name="exposeSpringMacroHelpers" value="true"/> <property name="cache" value="true" /> <property name="suffix" value=".html" /> <property name="order" value="1" /> </bean>
配置文件类: com.test.common.freemarker.CustomFreeMarkerConfigurer
public class CustomFreeMarkerConfigurer extends FreeMarkerConfigurer { @Override protected TemplateLoader getAggregateTemplateLoader( List<TemplateLoader> templateLoaders) { <!-- HtmlTemplateLoader 这个类用来自定义html模板 --> return new HtmlTemplateLoader(super.getAggregateTemplateLoader(templateLoaders)); } }
第三步:在html中使用freemark标签
<div οnclick="showHideDiv('${corpUser.corpUserProblemInfo.corpUserId}')">
<#list corpUser.forbiddenInfoList as forbiddenRecord>
<#if forbiddenRecord_index<2>
<div>
<span>${forbiddenRecord.time} </span>
<span>${forbiddenRecord.remark}</span>
</div>
<#else>
<div name="hideDiv${corpUser.corpUserProblemInfo.corpUserId}" style="display: none">
<span>${forbiddenRecord.time} </span>
<span>${forbiddenRecord.remark}</span>
</div>
</#if>
</#list>
</div>
自定义html模板类:HtmlTemplateLoader,加escape html指令, escape指令在解析模版时起作用,而不是运行时起作用
public class HtmlTemplateLoader implements TemplateLoader { private static final String HTML_ESCAPE_PREFIX= "<#escape x as x?html>"; private static final String HTML_ESCAPE_SUFFIX = "</#escape>"; private final TemplateLoader delegate; public HtmlTemplateLoader(TemplateLoader delegate) { this.delegate = delegate; } /* (non-Javadoc) * @see freemarker.cache.TemplateLoader#closeTemplateSource(java.lang.Object) */ @Override public void closeTemplateSource(Object templateSource) throws IOException { delegate.closeTemplateSource(templateSource); } /* (non-Javadoc) * @see freemarker.cache.TemplateLoader#findTemplateSource(java.lang.String) */ @Override public Object findTemplateSource(String name) throws IOException { return delegate.findTemplateSource(name); } /* (non-Javadoc) * @see freemarker.cache.TemplateLoader#getLastModified(java.lang.Object) */ @Override public long getLastModified(Object templateSource) { return delegate.getLastModified(templateSource); } /* (non-Javadoc) * @see freemarker.cache.TemplateLoader#getReader(java.lang.Object, java.lang.String) * 在读取template文件之后, 在前后套上<#escape>标签 */ @Override public Reader getReader(Object templateSource, String encoding) throws IOException { Reader reader = delegate.getReader(templateSource, encoding); String templateText = IOUtils.toString(reader); return new StringReader(HTML_ESCAPE_PREFIX+templateText + HTML_ESCAPE_SUFFIX); } }
escape指令body区的ftl的interpolations都会被自动加上escape表达式。但是不会影响字符串内的interpolations。而且也只会影响到body内出现的interpolations,比如不会影响到include的ftl的interpolations。
<#escape x as x?html>
First name: ${firstName}
Last name: ${lastName}
Maiden name: ${maidenName}
</#escape>
等同于:
Last name: ${lastName ?html}
Maiden name: ${maidenName ?html}