利用freemarker 靜態化網頁

轉載自:http://blog.csdn.net/ajun_studio/article/details/6932185


1、介紹-FreeMarker是什麼

     模板引擎:一種基於模板的、用來生成輸出文本的通用工具

     基於Java的開發包和類庫

    

2、介紹-FreeMarker能做什麼

     MVC框架中的View層組件

     Html頁面靜態化

    代碼生成工具

    CMS模板引擎

  頁面欄目動態定製

3、介紹-爲什麼要用FreeMarker

      程序邏輯(Java 程序)和頁面設計(FreeMarker模板)分離

      分層清晰,利於分工合作

      主流Web框架良好的集成(struts2,springmvc)

      簡單易學、功能強大

      免費開源

4、FreeMarker優點

     FreeMarker不依賴於Servlet,網絡或Web 環境

     FreeMarker一開始就是爲MVC設計的,它僅僅專注於展示

     你可以從任意位置加載模板;從類路徑下,從數據庫中等

     易於定義特設的宏和函數

5、上面簡單介紹一下Freemarker,下面主要是利用Freemarker實習網頁靜態化的功能。

通過上面的介紹知道Freemarker是一種基於模板(ftl文件)的、用來生成輸出文本的通用工具,所以我們必須要定製符合自己業務的模板出來,然後生成的我們得html頁面

Freemarker是通過freemarker.template.Configuration這個對象對模板進行加載的(它也處理創建和緩存預解析模板的工作),然後我們通過getTemplate方法獲得你想要的模板,有一點要記住freemarker.template.Configuration在你整個應用必須保證唯一實例。

5.1、在Configuration 中可以使用下面的方法來方便建立三種模板加載

  1. void setDirectoryForTemplateLoading(File dir);  

  1. void setClassForTemplateLoading(Class cl, String prefix);  

  1. void setServletContextForTemplateLoading(Object servletContext, String path);  
上述的第一種方法在磁盤的文件系統上設置了一個明確的目錄,它確定了從哪裏加載模板。不要說可能,File 參數肯定是一個存在的目錄。否則,將會拋出異常。
第二種調用方法使用了一個Class 類型的參數和一個前綴。這是讓你來指定什麼時候通過相同的機制來加載模板,不過是用Java 的ClassLoader 來加載類。這就意味着傳
入的Class 參數會被用來調用Class.getResource()方法來找到模板。參數prefix是給模板的名稱來加前綴的。在實際運行的環境中,類加載機制是首選用來加載模板的方法,因爲通常情況下,從類路徑下加載文件的這種機制,要比從文件系統的特定目錄位置加載安全而且簡單。在最終的應用程序中,所有代碼都使用.jar 文件打包也是不錯的,這樣用戶就可以直接執行包含所有資源的.jar 文件了。
第三種調用方式需要Web 應用的上下文和一個基路徑作爲參數,這個基路徑是Web 應用根路徑(WEB-INF 目錄的上級目錄)的相對路徑。那麼加載器將會從Web 應用目錄開
始加載模板。儘管加載方法對沒有打包的.war 文件起作用, 因爲它使用了ServletContext.getResource()方法來訪問模板,注意這裏我們指的是“目錄”。如果忽略了第二個參數(或使用了””),那麼就可以混合存儲靜態文件(.html,.jpg 等)和.ftl 文件,只是.ftl 文件可以被送到客戶端執行。當然必須在WEB-INF/web.xml中配置一個Servlet 來處理URI 格式爲*.ftl 的用戶請求,否則客戶端無法獲取到模板,因此你將會看到Web 服務器給出的祕密提示內容。在站點中不能使用空路徑,這將成爲一個問題,你應該在WEB-INF 目錄下的某個位置存儲模板文件,這樣模板源文件就不會偶然
void setDirectoryForTemplateLoading(File dir);
void setClassForTemplateLoading(Class cl, String prefix);
void setServletContextForTemplateLoading(Object
servletContext, String path);
地被執行到,這種機制對servlet 應用程序來加載模板來說,是非常好用的方式,而且模板可以自動更新而不需重啓Web 應用程序,但是對於類加載機制,這樣就行不通了。

5.2、從多個位置加載模板

  1. import freemarker.cache.*; // 模板加載器在這個包下  
  2. ...  
  3. FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates"));  
  4. FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates"));  
  5. ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(),"");  
  6. TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ftl2,ctl };  
  7. MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);  
  8. cfg.setTemplateLoader(mtl);  
現在,FreeMarker 將會嘗試從/tmp/templates 目錄加載模板,如果在這個目錄下沒有發現請求的模板,它就會繼續嘗試從/usr/data/templates 目錄下加載,如果還是沒有發現請求的模板,那麼它就會使用類加載器來加載模板。

5.3、封裝freemarker用於創建模板和加載模板

  1. package com.ajun.template.utils;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.Writer;  
  5. import java.util.Locale;  
  6. import java.util.Map;  
  7.   
  8. import javax.servlet.ServletContext;  
  9.   
  10. import freemarker.template.Configuration;  
  11. import freemarker.template.DefaultObjectWrapper;  
  12. import freemarker.template.Template;  
  13. import freemarker.template.TemplateException;  
  14.   
  15. /** 
  16.  * @author ajun 
  17.  * @http://blog.csdn.net/ajun_studio   
  18.  **/  
  19. public class FreeMarkertUtil {  
  20.   
  21.     private static  Configuration config = new Configuration();   
  22.       
  23.     /** 
  24.      * @param templateName 模板名字 
  25.      * @param root 模板根 用於在模板內輸出結果集 
  26.      * @param out 輸出對象 具體輸出到哪裏 
  27.      */  
  28.     public static void processTemplate(String templateName, Map<?,?> root, Writer out){  
  29.         try{  
  30.             //獲得模板  
  31.             Template template=config.getTemplate(templateName,"utf-8");  
  32.             //生成文件(這裏是我們是生成html)  
  33.             template.process(root, out);     
  34.             out.flush();     
  35.         } catch (IOException e) {  
  36.             e.printStackTrace();  
  37.         } catch (TemplateException e) {  
  38.             e.printStackTrace();  
  39.         }finally{  
  40.              try {  
  41.                 out.close();  
  42.                 out=null;  
  43.             } catch (IOException e) {  
  44.                 e.printStackTrace();  
  45.             }  
  46.         }  
  47.     }  
  48.     /** 
  49.      * 初始化模板配置 
  50.      * @param servletContext javax.servlet.ServletContext 
  51.      * @param templateDir 模板位置 
  52.      */  
  53.     public static void initConfig(ServletContext servletContext,String templateDir){  
  54.             config.setLocale(Locale.CHINA);  
  55.             config.setDefaultEncoding("utf-8");  
  56.             config.setEncoding(Locale.CHINA, "utf-8");  
  57.             config.setServletContextForTemplateLoading(servletContext, templateDir);  
  58.             config.setObjectWrapper(new DefaultObjectWrapper());  
  59.     }  
  60. }  

5.4、例子介紹

會用freemarker.jar自己google下載吧。

這個例子中我們會Freemarker生成一個html文件 包括html的頭部和尾部,以及body,這三個部分會分別對應三個模板文件,如下:

在模板內要想輸出結果集 可以用類似於EL表達式輸出${}

header.ftl

  1. companyName==>${h.companyName}<br/>  
  2. address==>${h.address}<br/>  
footer.ftl

  1. des==>${f.des}<br/>  
  2.   
  3. <a href="http://localhost/htmlpage/UpdateFooter.do"> 更新Footer </a>  

body.ftl,這個模板include以上兩個模板文件

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  2. <html>  
  3.   <head>  
  4.     <title>用戶列表</title>  
  5.       
  6.     <meta http-equiv="pragma" content="no-cache">  
  7.     <meta http-equiv="cache-control" content="no-cache">  
  8.     <meta http-equiv="expires" content="0">      
  9.     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  10.     <meta http-equiv="description" content="This is my page">  
  11.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  12.     <!--  
  13.     <link rel="stylesheet" type="text/css" href="styles.css">  
  14.     -->  
  15.    
  16.   </head>  
  17.     
  18.   <body>  
  19.   <#include "header.ftl" parse=true encoding="utf-8">  
  20.   <hr/>  
  21.   <a href="#">用戶列表</a><br/>  
  22.   <table border="1">  
  23.     <tr>  
  24.         <td>用戶名</td>  
  25.         <td>年齡</td>  
  26.         <td>生日</td>  
  27.         <td>id</td>  
  28.         <td>操作</td>  
  29.     </tr>  
  30.     <#list users as user>  
  31.         <tr>  
  32.             <td>${user.name}</td>  
  33.             <td>${user.age}</td>  
  34.             <td>  
  35.             ${user.birthday?string("yyyy-MM-dd HH:mm:ss")}  
  36.             </td>  
  37.             <td>${user.id}</td>  
  38.             <td><a href="http://localhost/htmlpage/DelUser.do?id=${user.id}">刪除</a></td>  
  39.         </tr>  
  40.     </#list>  
  41.       
  42.   </table>  
  43. <hr/>  
  44.   <#include "footer.ftl" parse=true encoding="utf-8">  
  45.   </body>  
  46. </html>  

這三個模板對應的三個實體類

Footer.java

  1. package com.ajun.template.bean;  
  2.   
  3. /** 
  4.  * @author ajun 
  5.  * @http://blog.csdn.net/ajun_studio   
  6.  **/  
  7. public class Footer {  
  8.   
  9.     private String des;  
  10.   
  11.     public String getDes() {  
  12.         return des;  
  13.     }  
  14.   
  15.     public void setDes(String des) {  
  16.         this.des = des;  
  17.     }  
  18.       
  19.       
  20. }  

Header.java

  1. package com.ajun.template.bean;  
  2. /** 
  3.  * @author ajun 
  4.  * @http://blog.csdn.net/ajun_studio   
  5.  **/  
  6. public class Header {  
  7.   
  8.     private String companyName;  
  9.       
  10.     private String address;  
  11.   
  12.     public String getCompanyName() {  
  13.         return companyName;  
  14.     }  
  15.   
  16.     public void setCompanyName(String companyName) {  
  17.         this.companyName = companyName;  
  18.     }  
  19.   
  20.     public String getAddress() {  
  21.         return address;  
  22.     }  
  23.   
  24.     public void setAddress(String address) {  
  25.         this.address = address;  
  26.     }  
  27.       
  28.       
  29.       
  30. }  

User.java

  1. package com.ajun.template.bean;  
  2.   
  3. import java.util.Date;  
  4.   
  5. public class User {  
  6.       
  7.     private Integer id;  
  8.   
  9.     private String name ;  
  10.       
  11.     private int age;  
  12.       
  13.     private Date birthday;  
  14.   
  15.     public String getName() {  
  16.         return name;  
  17.     }  
  18.   
  19.     public void setName(String name) {  
  20.         this.name = name;  
  21.     }  
  22.   
  23.     public int getAge() {  
  24.         return age;  
  25.     }  
  26.   
  27.     public void setAge(int age) {  
  28.         this.age = age;  
  29.     }  
  30.   
  31.     public Date getBirthday() {  
  32.         return birthday;  
  33.     }  
  34.   
  35.     public void setBirthday(Date birthday) {  
  36.         this.birthday = birthday;  
  37.     }  
  38.   
  39.       
  40.     public Integer getId() {  
  41.         return id;  
  42.     }  
  43.   
  44.     public void setId(Integer id) {  
  45.         this.id = id;  
  46.     }  
  47.   
  48.     public User(Integer id,String name, int age, Date birthday) {  
  49.         super();  
  50.         this.name = name;  
  51.         this.age = age;  
  52.         this.birthday = birthday;  
  53.         this.id = id;  
  54.     }  
  55.   
  56.     public User() {  
  57.         super();  
  58.     }  
  59.       
  60.       
  61. }  

下面模板一些業務邏輯操作,對這三個實體類

  1. package com.ajun.template.service;  
  2.   
  3. import com.ajun.template.bean.Footer;  
  4. /** 
  5.  * @author ajun 
  6.  * @http://blog.csdn.net/ajun_studio   
  7.  **/  
  8. public class FooterService {  
  9.   
  10.     private static Footer f = new Footer();  
  11.     static{  
  12.         f.setDes("北京-廊坊-好公司呢!!!!哇哈哈!!!");  
  13.     }  
  14.       
  15.     public static void update(String des){  
  16.         f.setDes(des);  
  17.     }  
  18.       
  19.     public static Footer gerFooter(){  
  20.         return f;  
  21.     }  
  22. }  

  1. package com.ajun.template.service;  
  2.   
  3. import com.ajun.template.bean.Header;  
  4. /** 
  5.  * @author ajun 
  6.  * @http://blog.csdn.net/ajun_studio   
  7.  **/  
  8. public class HeaderService {  
  9.   
  10.     private static Header h = new Header();  
  11.       
  12.     static{  
  13.         h.setAddress("北京朝陽CBD");  
  14.         h.setCompanyName("上海唐秀!!!");  
  15.     }  
  16.       
  17.     public static void update(String address,String companyName){  
  18.         h.setAddress(address);  
  19.         h.setCompanyName(companyName);  
  20.     }  
  21.       
  22.     public static Header getHeader(){  
  23.         return h;  
  24.     }  
  25. }  
  1. package com.ajun.template.service;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Date;  
  5. import java.util.List;  
  6.   
  7. import com.ajun.template.bean.User;  
  8. /** 
  9.  * @author ajun 
  10.  * @http://blog.csdn.net/ajun_studio   
  11.  **/  
  12. public class UserService {  
  13.   
  14.     private static List<User> users = new ArrayList<User>();  
  15.       
  16.     static{  
  17.         for(int i=0;i<10;i++){  
  18.             User u = new User(i,"ajun"+i,i+10,new Date());  
  19.             users.add(u);  
  20.         }  
  21.     }  
  22.       
  23.     public static List<User> getUsers(){  
  24.         return users;  
  25.     }  
  26.       
  27.     public static void delete(int index){  
  28.         for(int i=0 ;i<users.size();i++){  
  29.             User u = users.get(i);  
  30.             if(u.getId()==index){  
  31.                 users.remove(u);  
  32.                 //users.remove(index);  
  33.             }  
  34.         }  
  35.     }  
  36. }  

上面主要是模板你的一些業務和dao層得操作,因此沒有涉及數據庫的操作,主要是爲實驗。

生成html對外調用的方法,會用到FreeMarkertUtil這個類 這個類得代碼上面已經給出。

  1. package com.ajun.template.client;  
  2.   
  3. import java.io.Writer;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7.   
  8. import com.ajun.template.bean.Footer;  
  9. import com.ajun.template.bean.Header;  
  10. import com.ajun.template.bean.User;  
  11. import com.ajun.template.service.FooterService;  
  12. import com.ajun.template.service.HeaderService;  
  13. import com.ajun.template.service.UserService;  
  14. import com.ajun.template.utils.FreeMarkertUtil;  
  15.   
  16. /** 
  17.  * @author ajun 
  18.  * @http://blog.csdn.net/ajun_studio   
  19.  **/  
  20. public class ProcessClient {  
  21.   
  22.     private static Map<String,Object> root = new HashMap<String,Object>();  
  23.   
  24.     /** 
  25.      * 調用FreeMarkertUtil.java 
  26.      * FreeMarkertUtil.processTemplate("body.ftl", root, out); 
  27.      * 來生成html文件 
  28.      * @param out 
  29.      */  
  30.     public static void processBody(Writer out){  
  31.         Header h = HeaderService.getHeader();  
  32.         root.put("h", h);  
  33.         Footer f = FooterService.gerFooter();  
  34.         root.put("f", f);  
  35.         List<User> users = UserService.getUsers();  
  36.         root.put("users", users);  
  37.         FreeMarkertUtil.processTemplate("body.ftl", root, out);  
  38.     }  
  39.       
  40. }  
此時我會提供一個servlet在客戶端進行第一次請求的時候 我會調用這個ProcessClient來生成html頁面,之後每次訪問就可以直接訪問html,來做到真正的靜態化了

  1. package com.ajun.template.servlet;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.OutputStreamWriter;  
  7. import java.io.Writer;  
  8.   
  9. import javax.servlet.ServletConfig;  
  10. import javax.servlet.ServletException;  
  11. import javax.servlet.http.HttpServlet;  
  12. import javax.servlet.http.HttpServletRequest;  
  13. import javax.servlet.http.HttpServletResponse;  
  14.   
  15. import com.ajun.template.client.ProcessClient;  
  16. import com.ajun.template.utils.DirectoryFilter;  
  17. import com.ajun.template.utils.FreeMarkertUtil;  
  18.   
  19. /** 
  20.  * @author ajun 
  21.  * @http://blog.csdn.net/ajun_studio   
  22.  **/  
  23. public class Index extends HttpServlet {  
  24.   
  25.     private static final long serialVersionUID = 7474850489594438527L;  
  26.   
  27.     public Index() {  
  28.         super();  
  29.     }  
  30.   
  31.       
  32.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  33.             throws ServletException, IOException {  
  34.   
  35.         this.doPost(request, response);  
  36.     }  
  37.   
  38.       
  39.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  40.             throws ServletException, IOException {  
  41.         //html生成之後存放的路徑  
  42.         String dirPath = request.getSession().getServletContext().getRealPath("/templates/html");  
  43.         File path = new File(dirPath);  
  44.         //生成的文件的名字  
  45.         String indexFileName = "index.html";  
  46.         /** 
  47.          * 判斷是否已經存在該html文件,存在了就直接訪問html ,不存在生成html文件 
  48.          */  
  49.         String[] indexfileList = path.list(new DirectoryFilter(indexFileName));  
  50.         if(indexfileList.length<=0){  
  51.             Writer out = new OutputStreamWriter(new FileOutputStream(dirPath+"/"+indexFileName),"UTF-8");  
  52.             //生成html文件  
  53.             ProcessClient.processBody(out);  
  54.             request.getRequestDispatcher("/templates/html/index.html").forward(request, response);   
  55.         }else{  
  56.             request.getRequestDispatcher("/templates/html/"+indexfileList[0]).forward(request, response);   
  57.         }  
  58.           
  59.       
  60.     }  
  61.   
  62.       
  63.   
  64.     /** 
  65.      * 初始化模板配置,供以後獲得模板,在init里加載也主要是爲保證Configuration實例唯一 
  66.      */  
  67.     public void init(ServletConfig config) throws ServletException {  
  68.         String templateDir = config.getInitParameter("templateDir");  
  69.         FreeMarkertUtil.initConfig(config.getServletContext(), templateDir);  
  70.     }  
  71.   
  72.       
  73. }  
web.xml配置

  1. <servlet>  
  2.    <description>This is the description of my J2EE component</description>  
  3.    <display-name>This is the display name of my J2EE component</display-name>  
  4.    <servlet-name>Index</servlet-name>  
  5.    <servlet-class>com.ajun.template.servlet.Index</servlet-class>  
  6.    <init-param>  
  7.     <param-name>templateDir</param-name>模板存放位置,是基於app的根目錄的  
  8.     <param-value>/templates</param-value>  
  9.    </init-param>  
  10.    <load-on-startup>3</load-on-startup>爲了啓動的時候初始化模板配置  
  11.  </servlet>  
  12.   
  13.  <servlet-mapping>  
  14.    <servlet-name>Index</servlet-name>  
  15.    <url-pattern>/Index.do</url-pattern>  
  16.  </servlet-mapping>  

部署到tomcat上,輸入:http://localhost/htmlpage/Index.do

頁面效果:

頁面是做好了,但是內容變化了 ,更新怎麼辦呢,我這裏是當列表內容變化之後 ,我是刪除原來的html ,利用模板然後重新生成的符合新結果的html頁面

當我刪除一條的時候,我會重新生成html頁面,但是由於瀏覽器緩存的原因,即是你刪除了,重新生成了新html頁面,可是瀏覽器還是保存原來的頁面,不刷新兩次是不行的,

這裏我採用的沒更新的時候,都會給這個html改個名字,讓瀏覽器去加載最新的,就可以了

具體的刪除操作如下:

  1. package com.ajun.template.servlet;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.OutputStreamWriter;  
  7. import java.io.Writer;  
  8. import java.util.UUID;  
  9.   
  10. import javax.servlet.ServletException;  
  11. import javax.servlet.http.HttpServlet;  
  12. import javax.servlet.http.HttpServletRequest;  
  13. import javax.servlet.http.HttpServletResponse;  
  14.   
  15. import com.ajun.template.client.ProcessClient;  
  16. import com.ajun.template.service.UserService;  
  17. import com.ajun.template.utils.DirectoryFilter;  
  18. /** 
  19.  * @author ajun 
  20.  * @http://blog.csdn.net/ajun_studio   
  21.  **/  
  22. public class DelUser extends HttpServlet {  
  23.   
  24.       
  25.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  26.             throws ServletException, IOException {  
  27.             this.doPost(request, response);  
  28.     }  
  29.   
  30.     //刪除用戶  
  31.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  32.             throws ServletException, IOException {  
  33.           
  34.         String id = request.getParameter("id");  
  35.         UserService.delete(Integer.valueOf(id));  
  36.           
  37.         //生成html的位置  
  38.         String dirPath = request.getSession().getServletContext().getRealPath("/templates/html");  
  39.         //文件名字  
  40.         String indexFileName = "index.html";  
  41.           
  42.         //刪除原來的文件  
  43.         delOldHtml(dirPath,indexFileName);  
  44.           
  45.         //防止瀏覽器緩存,用於重新生成新的html  
  46.         UUID uuid = UUID.randomUUID();  
  47.         Writer out = new OutputStreamWriter(new FileOutputStream(dirPath+"/"+uuid+indexFileName),"UTF-8");  
  48.         ProcessClient.processBody(out);  
  49.         response.sendRedirect("templates/html/"+uuid+"index.html");  
  50.     }  
  51.       
  52.     /** 
  53.      * 刪除原來的html文件 
  54.      * @param htmlDir 
  55.      * @param htmlName 
  56.      */  
  57.     private void delOldHtml(String htmlDir,String htmlName){  
  58.         File path = new File(htmlDir);  
  59.         String[] indexfileList = path.list(new DirectoryFilter(htmlName));  
  60.         if(indexfileList.length>=0){  
  61.             for(String f:indexfileList){  
  62.                 File delf = new File(htmlDir+"/"+f);  
  63.                 delf.delete();  
  64.             }  
  65.         }  
  66.     }  
  67.   
  68. }  

通過以上操作,每次更新html,就可以不解決瀏覽器緩存的問題了。

還有一個工具類需要介紹,就是判斷是否已經生成了特定的html文件的java類

  1. package com.ajun.template.utils;  
  2.   
  3. import java.io.File;  
  4. import java.io.FilenameFilter;  
  5. /** 
  6.  * @author ajun 
  7.  * @http://blog.csdn.net/ajun_studio   
  8.  **/  
  9. public class DirectoryFilter implements FilenameFilter {  
  10.   
  11.     String myString;  
  12.     public DirectoryFilter(String myString)  
  13.     {  
  14.         this.myString = myString;  
  15.     }  
  16.       
  17.     public boolean accept(File dir,String name)  
  18.     {   //FilenameFilter.accept(File dir, String name)   
  19.        // 測試指定文件是否應該包含在某一文件列表中。  
  20.         String f= new File(name).getName();  
  21.         if(f.contains(myString) || f.equals(myString)){  
  22.             return true;  
  23.         }  
  24.         return false;  
  25.     }  
  26.   
  27. }  

到這裏整個靜態化就完成了,靜態化更新機制,是根據你自己項目的業務進行定製的,可以定時生成html文件,也可以需要手動生成。

項目結構圖如下:


記住:網站不是所有的頁面都是需要靜態化的,主要是一些實時性不是很高的數據頁面進行靜態化(來提高訪問速度),其他都是通過僞靜態來實現的,就是重寫utl。

頁面靜態化不是提高網站性能的唯一途徑,還可以利用一些緩存產品來實現。


常用FreeMarker資源

官網主頁:http://www.freemarker.org/

Eclipse插件JbossTool:http://www.jboss.org/tools/download/

中文文檔:https://sourceforge.net/projects/freemarker/files/chinese-manual/FreeMarker_Manual_zh_CN.pdf/download

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章