天天看點

模闆:velocity和freemarker的比較[轉

關鍵字: 模闆技術

模闆技術在現代的軟體開發中有着重要的地位,而目前最流行的兩種模闆技術恐怕要算freemarker和velocity 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好,如果你是用idea那很遺憾,我沒有找到類似的插件。好在很多地方呢,我看到的是freemarker的插件除了支援freemarker文法也支援html語句,而velocity 的插件貌似隻支援velocity 的文法,html就隻是用普通的文本來顯示了,在這一點上freemarker占上風了(不要和我說高手都是用windows記事本之類的話,這本來就違背了模闆技術的初衷)

3freemarker對jsptag的支援很好,算了,不到迫不得已還是不要這樣做吧。

還有就是兩者的文法格式,這一點上不同的人有不同傾向

下面就介紹一下這個例子吧

了,webwork2.2對兩者都有不錯的支援,也就是說在webwork2中你可以随意選擇使用freemarker或

Java代碼

模闆:velocity和freemarker的比較[轉
  1. public   class  TemplateTest {   
  2.      public   static   void  main(String[] args)  throws  Exception{   
  3.         Map latest =  new  HashMap();   
  4.         latest.put( "url" ,  "products/greenmouse.html" );   
  5.         latest.put( "name" ,  "green mouse" );   
  6.         Map root =  new  HashMap();   
  7.         root.put( "user" ,  "Big Joe" );   
  8.         root.put( "latestProduct" , latest);   
  9.         root.put( "number" ,  new  Long( 2222 ));   
  10.         root.put( "date" , new  Date());   
  11.         List listTest =  new  ArrayList();   
  12.         listTest.add( "1" );   
  13.         listTest.add( "2" );   
  14.         root.put( "list" ,listTest);   
  15.         TemplateEngine freemarkerEngine = (TemplateEngine)TemplateFactory.getInstance().getBean( "freemarker" );   
  16.         freemarkerEngine.run(root); //使用freemarker模闆技術   
  17.         TemplateEngine velocityEngine = (TemplateEngine)TemplateFactory.getInstance().getBean( " velocity " );   
  18.         velocityEngine.run(root); //使用 velocity 模闆技術   
  19.     }   
  20. }  
/**
 * 
 * @author 張榮華
 * 轉載請注明出處
 */
public class TemplateTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		/* 準備資料 */
        Map latest = new HashMap();
        latest.put("url", "products/greenmouse.html");
        latest.put("name", "green mouse");
        
        Map root = new HashMap();
        root.put("user", "Big Joe");
        root.put("latestProduct", latest);
        root.put("number", new Long(2222));
        root.put("date",new Date());
        
        List listTest = new ArrayList();
        listTest.add("1");
        listTest.add("2");
        
        root.put("list",listTest);
        
        TemplateEngine freemarkerEngine = (TemplateEngine)TemplateFactory.getInstance().getBean("freemarker");
        freemarkerEngine.run(root);//使用freemarker模闆技術
        
        TemplateEngine velocityEngine = (TemplateEngine)TemplateFactory.getInstance().getBean("velocity


velocity




");
        velocityEngine.run(root);//使用
模闆技術
	}

}
           

工廠類,用來得到模闆引擎

Java代碼

模闆:velocity和freemarker的比較[轉
  1. public   class  TemplateFactory {   
  2.      private   static  TemplateFactory instance;   
  3.      private  Map objectMap;   
  4.      static {   
  5.         instance =  new  TemplateFactory();   
  6.     }   
  7.      public  TemplateFactory() {   
  8.          super ();   
  9.          this .objectMap =  new  HashMap();   
  10.          synchronized  ( this ) {   
  11.             objectMap.put( "freemarker" ,  new  FreemarkerTemplateEngine(){   
  12.                  public  String getTemplatePath() {   
  13.                      return   "template" ;   
  14.                 }   
  15.             });   
  16.             objectMap.put( " velocity " ,  new  VelocityTemplateEngine());   
  17.         }   
  18.     }   
  19.      public   static  TemplateFactory getInstance(){   
  20.          return  instance;   
  21.     }   
  22.      public  Object getBean(String beanName){   
  23.          return  objectMap.get(beanName);   
  24.     }   
  25. }  
/**
 * 
 * @author 張榮華
 * 轉載請注明出處
 */
public class TemplateFactory {
	private static TemplateFactory instance;
	private Map objectMap;
	
	static{
		instance = new TemplateFactory();
	}
	
	public TemplateFactory() {
		super();
		this.objectMap = new HashMap();
		synchronized (this) {
			objectMap.put("freemarker", new FreemarkerTemplateEngine(){
				public String getTemplatePath() {
					return "template";
				}
			});
			
			objectMap.put("velocity




", new VelocityTemplateEngine());
		}
	}

	public static TemplateFactory getInstance(){
		return instance;
	}
	
	/**
	 * 模仿spring的工廠
	 * @param beanName
	 * @return
	 */
	public Object getBean(String beanName){
		return objectMap.get(beanName);
	}

}
           

引擎接口

Java代碼

模闆:velocity和freemarker的比較[轉
  1. public   interface  TemplateEngine {   
  2.      void  run(Map context) throws  Exception;   
  3. }  
/**
 * 
 * @author 張榮華
 * 轉載請注明出處
 */
public interface TemplateEngine {
	
	void run(Map context)throws Exception;

}
           

模闆引擎的實作使用method template模式,因為有兩個實作,這兩個實作又存在公共的邏輯,是以選擇了這個模式

Java代碼

模闆:velocity和freemarker的比較[轉
  1. public   abstract   class  AbstractTemplateEngine  implements  TemplateEngine{   
  2.      public   abstract  String getTemplatePath();   
  3.      public   abstract  String getTemplate();   
  4.      public   abstract  String getEngineType();   
  5.      public   void  run(Map context) throws  Exception{   
  6.          if (Constants.ENGINE_TYPE_FREEMARKER.equals(getEngineType()))   
  7.             executeFreemarker(context);   
  8.          else   
  9.             executeVelocity(context);   
  10.     }   
  11.      private   void  executeFreemarker(Map context) throws  Exception{   
  12.         Configuration cfg =  new  Configuration();   
  13.         cfg.setDirectoryForTemplateLoading(   
  14.                  new  File(getTemplatePath()));   
  15.         cfg.setObjectWrapper( new  DefaultObjectWrapper());   
  16.         cfg.setCacheStorage( new  freemarker.cache.MruCacheStorage( 20 ,  250 ));   
  17.         Template temp = cfg.getTemplate(getTemplate());   
  18.         Writer out =  new  OutputStreamWriter(System.out);   
  19.         temp.process(context, out);   
  20.         out.flush();   
  21.     }   
  22.      private   void  executeVelocity(Map root) throws  Exception{   
  23.         Velocity .init();   
  24.         VelocityContext context =  new  VelocityContext(root);   
  25.         org.apache.velocity .Template template =  null ;   
  26.         template = Velocity .getTemplate(getTemplatePath()+getTemplate());   
  27.         StringWriter sw =  new  StringWriter();   
  28.         template.merge( context, sw );   
  29.         System.out.print(sw.toString());   
  30.     }   
  31. }  
/**
 * 
 * @author 張榮華
 * 轉載請注明出處
 */
public abstract class AbstractTemplateEngine implements TemplateEngine{

	public abstract String getTemplatePath();
	
	public abstract String getTemplate();
	
	public abstract String getEngineType();
	
	public void run(Map context)throws Exception{
		if(Constants.ENGINE_TYPE_FREEMARKER.equals(getEngineType()))
			executeFreemarker(context);
		else
			executeVelocity(context);
	}
	
	private void executeFreemarker(Map context)throws Exception{
		Configuration cfg = new Configuration();
	    cfg.setDirectoryForTemplateLoading(
	            new File(getTemplatePath()));
	    cfg.setObjectWrapper(new DefaultObjectWrapper());
	    
	    cfg.setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250));
	            
	    Template temp = cfg.getTemplate(getTemplate());

	    Writer out = new OutputStreamWriter(System.out);
	    temp.process(context, out);
	    out.flush();
	}
	
	private void executeVelocity(Map root)throws Exception{
		
		Velocity


velocity


Velocity




.init();
		VelocityContext context = new VelocityContext(root);
		org.apache.
.Template template = null;
		
	    template = 
.getTemplate(getTemplatePath()+getTemplate());
	    
		StringWriter sw = new StringWriter();
		template.merge( context, sw );
		System.out.print(sw.toString());

	}

}
           

這個是freemarker實作

Java代碼

模闆:velocity和freemarker的比較[轉
  1. public   class  FreemarkerTemplateEngine  extends  AbstractTemplateEngine{   
  2.      private   static   final  String DEFAULT_TEMPLATE =  "FreemarkerExample.ftl" ;   
  3.      public  String getTemplatePath() {   
  4.          return   null ;   
  5.     }   
  6.      public   void  run(Map root)  throws  Exception{   
  7.          super .run(root);   
  8.     }   
  9.      public  String getTemplate() {   
  10.          // TODO Auto-generated method stub   
  11.          return  DEFAULT_TEMPLATE;   
  12.     }   
  13.      public  String getEngineType() {   
  14.          return  Constants.ENGINE_TYPE_FREEMARKER;   
  15.     }   
  16. }  
/**
 * 
 * @author 張榮華
 * 轉載請注明出處
 */
public class FreemarkerTemplateEngine extends AbstractTemplateEngine{
	private static final String DEFAULT_TEMPLATE = "FreemarkerExample.ftl";
	
	/**
	 * 這個方法應該實作的是讀取配置檔案
	 */
	public String getTemplatePath() {
		return null;
	}
	
	public void run(Map root) throws Exception{
		super.run(root);
	}

	public String getTemplate() {
		// TODO Auto-generated method stub
		return DEFAULT_TEMPLATE;
	}

	public String getEngineType() {
		return Constants.ENGINE_TYPE_FREEMARKER;
	}
}
           

這個是velocity 實作

Java代碼

模闆:velocity和freemarker的比較[轉
  1. public   class  VelocityTemplateEngine  extends  AbstractTemplateEngine{   
  2. private   static   final  String DEFAULT_TEMPLATE =  "VelocityExample.vm" ;   
  3.      public  String getTemplatePath() {   
  4.          return   "/template/" ;   
  5.     }   
  6.      public   void  run(Map map)  throws  Exception{   
  7.          super .run(map);   
  8.     }   
  9.      public  String getTemplate() {   
  10.          // TODO Auto-generated method stub   
  11.          return  DEFAULT_TEMPLATE;   
  12.     }   
  13.      public  String getEngineType() {   
  14.          // TODO Auto-generated method stub   
  15.          return  Constants.ENGINE_TYPE_VELOCITY;   
  16.     }   
  17. }  
/**
 * 
 * @author 張榮華
 * 轉載請注明出處
 */
public class VelocityTemplateEngine extends AbstractTemplateEngine{

private static final String DEFAULT_TEMPLATE = "VelocityExample.vm";

	public String getTemplatePath() {
		return "/template/";
	}
	
	public void run(Map map) throws Exception{
		super.run(map);
	}

	public String getTemplate() {
		// TODO Auto-generated method stub
		return DEFAULT_TEMPLATE;
	}

	public String getEngineType() {
		// TODO Auto-generated method stub
		return Constants.ENGINE_TYPE_VELOCITY;
	}
}
           

以下是模闆

1,freemarker模闆

Java代碼

模闆:velocity和freemarker的比較[轉
  1. freemarker template test:   
  2. string test-----------${user}-----------${number}-----------${latestProduct.url}-----------${latestProduct.name}   
  3. condition test-----------   
  4. <# if  user ==  "Big Joe" >   
  5. list iterator-----------   
  6. <#list list as aa>   
  7. ${aa}   
  8. </#list>    
  9. </# if >   
  10. date test-----------${date?string( "MMM/dd/yyyy" )}  
freemarker template test:
string test-----------${user}-----------${number}-----------${latestProduct.url}-----------${latestProduct.name}
condition test-----------
<#if user == "Big Joe">
list iterator-----------
<#list list as aa>
${aa}
</#list> 
</#if>
date test-----------${date?string("MMM/dd/yyyy")}
           

2,velocity 模闆

Java代碼

模闆:velocity和freemarker的比較[轉
  1. ******************************************************************************************************************   
  2. velocity  template test:   
  3. string test-----------${user}-----------${number}-----------${latestProduct.url}-----------${latestProduct.name}   
  4. condition test-----------   
  5. # if  ($user ==  "Big Joe" )   
  6. list iterator-----------   
  7. #foreach( $aa in $list )   
  8. $aa   
  9. #end   
  10. #end   
  11. date test-----------${date}  
******************************************************************************************************************
velocity




 template test:
string test-----------${user}-----------${number}-----------${latestProduct.url}-----------${latestProduct.name}
condition test-----------
#if ($user == "Big Joe")
list iterator-----------
#foreach( $aa in $list )
$aa
#end
#end
date test-----------${date}
           

至此整個例子就結束了,以上隻是最簡單的介紹,當然這兩種技術還有待我們的深入研究。這個例子隻不過是比較直覺的表現兩種技術的使用而已

而且如果想學習方法模闆模式和工廠模式的同學可以下載下傳代碼看看

作者:張榮華,未經作者同意不得随意轉載!