引用 模板:velocity和freemarker的比较

引用

火炎焱燚的模板:velocity和freemarker的比较

/**

*作者:张荣华(ahuaxuan)

*2007-04-16

*转载请注明出处及作者

*/

模板技术在现代的软件开发中有着重要的地位,而目前最流行的两种模板技术恐怕要算freemarker和velocity了,webwork2.2对两者都有不错的支持,也就是说在webwork2中你可以随意选择使用freemarker或velocity作为view,模板技术作为view的好处是很多,尤其和jsp比较起来优点更大,众所周知jsp需要在第一次被执行的时候编译成servlet,那么这个过程是很慢的,当然很多应用服务器都提供预编译的功能,但是在开发的时候仍然给我们程序员带来了很多痛苦,每次修改都要多几秒钟,那在一天的开发中就有很多时间浪费在jsp的编译上了。用webworkinaction的作者的话来说:“每次修改之后重新运行都要等等几秒是令人失望的,而频繁地修改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好,如果你是用idea那很遗憾,我没有找到类似的插件。好在很多地方呢,我看到的是freemarker的插件除了支持freemarker语法也支持html语句,而velocity的插件貌似只支持velocity的语法,html就只是用普通的文本来显示了,在这一点上freemarker占上风了(不要和我说高手都是用windows记事本之类的话,这本来就违背了模板技术的初衷)

3freemarker对jsptag的支持很好,算了,不到迫不得已还是不要这样做吧。

还有就是两者的语法格式,这一点上不同的人有不同倾向

下面就介绍一下这个例子吧

Java代码

/**

*

*@author张荣华

*转载请注明出处

*/

publicclassTemplateTest{

/**

*@paramargs

*/

publicstaticvoidmain(String[]args)throwsException{

/*准备数据*/

Maplatest=newHashMap();

latest.put("url","products/greenmouse.html");

latest.put("name","greenmouse");

Maproot=newHashMap();

root.put("user","BigJoe");

root.put("latestProduct",latest);

root.put("number",newLong(2222));

root.put("date",newDate());

ListlistTest=newArrayList();

listTest.add("1");

listTest.add("2");

root.put("list",listTest);

TemplateEnginefreemarkerEngine=(TemplateEngine)TemplateFactory.getInstance().getBean("freemarker");

freemarkerEngine.run(root);//使用freemarker模板技术

TemplateEnginevelocityEngine=(TemplateEngine)TemplateFactory.getInstance().getBean("velocity");

velocityEngine.run(root);//使用velocity模板技术

}

}

工厂类,用来得到模板引擎

Java代码

/**

*

*@author张荣华

*转载请注明出处

*/

publicclassTemplateFactory{

privatestaticTemplateFactoryinstance;

privateMapobjectMap;

static{

instance=newTemplateFactory();

}

publicTemplateFactory(){

super();

this.objectMap=newHashMap();

synchronized(this){

objectMap.put("freemarker",newFreemarkerTemplateEngine(){

publicStringgetTemplatePath(){

return"template";

}

});

objectMap.put("velocity",newVelocityTemplateEngine());

}

}

publicstaticTemplateFactorygetInstance(){

returninstance;

}

/**

*模仿spring的工厂

*@parambeanName

*@return

*/

publicObjectgetBean(StringbeanName){

returnobjectMap.get(beanName);

}

}

引擎接口

Java代码

/**

*

*@author张荣华

*转载请注明出处

*/

publicinterfaceTemplateEngine{

voidrun(Mapcontext)throwsException;

}

模板引擎的实现使用methodtemplate模式,因为有两个实现,这两个实现又存在公共的逻辑,所以选择了这个模式

Java代码

/**

*

*@author张荣华

*转载请注明出处

*/

publicabstractclassAbstractTemplateEngineimplementsTemplateEngine{

publicabstractStringgetTemplatePath();

publicabstractStringgetTemplate();

publicabstractStringgetEngineType();

publicvoidrun(Mapcontext)throwsException{

if(Constants.ENGINE_TYPE_FREEMARKER.equals(getEngineType()))

executeFreemarker(context);

else

executeVelocity(context);

}

privatevoidexecuteFreemarker(Mapcontext)throwsException{

Configurationcfg=newConfiguration();

cfg.setDirectoryForTemplateLoading(

newFile(getTemplatePath()));

cfg.setObjectWrapper(newDefaultObjectWrapper());

cfg.setCacheStorage(newfreemarker.cache.MruCacheStorage(20,250));

Templatetemp=cfg.getTemplate(getTemplate());

Writerout=newOutputStreamWriter(System.out);

temp.process(context,out);

out.flush();

}

privatevoidexecuteVelocity(Maproot)throwsException{

Velocity.init();

VelocityContextcontext=newVelocityContext(root);

org.apache.velocity.Templatetemplate=null;

template=Velocity.getTemplate(getTemplatePath()+getTemplate());

StringWritersw=newStringWriter();

template.merge(context,sw);

System.out.print(sw.toString());

}

}

这个是freemarker实现

Java代码

/**

*

*@author张荣华

*转载请注明出处

*/

publicclassFreemarkerTemplateEngineextendsAbstractTemplateEngine{

privatestaticfinalStringDEFAULT_TEMPLATE="FreemarkerExample.ftl";

/**

*这个方法应该实现的是读取配置文件

*/

publicStringgetTemplatePath(){

returnnull;

}

publicvoidrun(Maproot)throwsException{

super.run(root);

}

publicStringgetTemplate(){

//TODOAuto-generatedmethodstub

returnDEFAULT_TEMPLATE;

}

publicStringgetEngineType(){

returnConstants.ENGINE_TYPE_FREEMARKER;

}

}

这个是velocity实现

Java代码

/**

*

*@author张荣华

*转载请注明出处

*/

publicclassVelocityTemplateEngineextendsAbstractTemplateEngine{

privatestaticfinalStringDEFAULT_TEMPLATE="VelocityExample.vm";

publicStringgetTemplatePath(){

return"/template/";

}

publicvoidrun(Mapmap)throwsException{

super.run(map);

}

publicStringgetTemplate(){

//TODOAuto-generatedmethodstub

returnDEFAULT_TEMPLATE;

}

publicStringgetEngineType(){

//TODOAuto-generatedmethodstub

returnConstants.ENGINE_TYPE_VELOCITY;

}

}

以下是模板

1,freemarker模板

Java代码

freemarkertemplatetest:

stringtest-----------${user}-----------${number}-----------${latestProduct.url}-----------${latestProduct.name}

conditiontest-----------

<#ifuser=="BigJoe">

listiterator-----------

<#listlistasaa>

${aa}

</#list>

</#if>

datetest-----------${date?string("MMM/dd/yyyy")}

2,velocity模板

Java代码

******************************************************************************************************************

velocitytemplatetest:

stringtest-----------${user}-----------${number}-----------${latestProduct.url}-----------${latestProduct.name}

conditiontest-----------

#if($user=="BigJoe")

listiterator-----------

#foreach($aain$list)

$aa

#end

#end

datetest-----------${date}

至此整个例子就结束了,以上只是最简单的介绍,当然这两种技术还有待我们的深入研究。这个例子只不过是比较直观的表现两种技术的使用而已

而且如果想学习方法模板模式和工厂模式的同学可以下载代码看看

相关推荐