Static Web Page Using freemarker

Keywords: Java FreeMarker xml encoding

Statement: This article is from: http://blog.csdn.net/ajun_studio/article/details/6932185/


1. Introduction - What is FreeMarker

Template Engine: A Template-based Common Tool for Generating Output Text

Based on Java Development kits and class libraries

    

2. Introduction - What FreeMarker Can Do

View Layer Components in MVC Framework

Static Html pages

Code Generation Tool

CMS Template Engine

Dynamic customization of page columns

3. Introduction - Why use FreeMarker

Separation of Program Logic (Java Program) and Page Design (FreeMarker Template)

Clear layers are conducive to division of labour and cooperation

Good integration of mainstream Web frameworks (struts 2, spring mvc)

Easy to learn and powerful

Free and open source

4. Advantages of FreeMarker

FreeMarker does not depend on Servlet, network or Web environments

FreeMarker was originally designed for MVC and focused only on presentation.

You can load templates from anywhere; from the classpath, from the data base secondary

Easy to define ad hoc macrosum functions

5. The above is a brief introduction to Freemarker. The following is mainly to use the static function of Freemarker internship web page.

From the introduction above, we know that Freemarker is a template-based general tool for generating output text, so we have to customize the template that suits our business, and then generate our html pages.

Freemarker loads templates through the freemarker.template.Configuration object (it also handles creating and caching pre-parsing templates), and then we get the template you want through the getTemplate method. One thing to remember is that freemarker.template.Configuration must guarantee a unique instance throughout your application.

5.1. In Configuration, the following methods can be used to facilitate the establishment of three template loads

  1. void setDirectoryForTemplateLoading(File dir);  

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

  1. void setServletContextForTemplateLoading(Object servletContext, String path);  
The first method described above sets up a clear directory on the disk's file system, which determines where to load the template. Don't say it's possible, the File parameter must be an existing directory. Otherwise, an exception will be thrown.
The second invocation method uses a Class type parameter and a prefix. This lets you specify when to load templates through the same mechanism, but using Java lassLoader to load classes. This means transmission.
The incoming Class parameter is used to call the Class.getResource() method to find the template. The prefix parameter prefixes the name of the template. In the actual running environment, class loading mechanism is the preferred method to load templates, because it is usually safer and simpler to load files from the classpath than from the specific directory location of the file system. In the final application, it's also good to package all the code in A. jar file so that the user can directly execute the. jar file containing all the resources.
The third method of invocation requires the context of the Web application and a base path, which is the relative path of the Web application root path (the directory of the WEB-INF directory). Then the loader will be opened from the Web application directory
Start loading the template. Although the loading method works for unpackaged. war files, because it uses the ServletContext.getResource() method to access templates, note that we mean "directories" here. If the second parameter is omitted (or used"), then static files (. html,. jpg, etc.) and. FTL files can be mixed, but. FTL files can be sent to the client for execution. Of course, you have to configure a Servlet in WEB-INF/web.xml to process URI format as *.ftl User requests, otherwise the client can not get the template, so you will see the content of the secret prompt given by the Web server. You can't use empty paths in your site. This will be a problem. You should store template files somewhere in the WEB-INF directory so that template source files are not accidental.
void setDirectoryForTemplateLoading(File dir);
void setClassForTemplateLoading(Class cl, String prefix);
void setServletContextForTemplateLoading(Object
servletContext, String path);
To be implemented, this mechanism is a very useful way for servlet applications to load templates, and templates can be automatically updated without restarting Web applications, but for class loading mechanisms, this is not feasible.

5.2. Loading templates from multiple locations

  1. import freemarker.cache.*; //Template loader under this package  
  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);  
Now FreeMarker will try to load templates from the / tmp/templates directory. If no requested templates are found in this directory, it will continue to try to load templates from the / usr/data/templates directory. If no requested templates are found, it will use a class loader to load templates.

5.3. Encapsulate freemarker for creating and loading templates

  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 Template name 
  25.      * @param root Template roots are used to output result sets within templates 
  26.      * @param out Output Object: Where to Export 
  27.      */  
  28.     public static void processTemplate(String templateName, Map<?,?> root, Writer out){  
  29.         try{  
  30.             //Getting Templates  
  31.             Template template=config.getTemplate(templateName,"utf-8");  
  32.             //Generate files (here we are generating 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.      * Initialization Template Configuration 
  50.      * @param servletContext javax.servlet.ServletContext 
  51.      * @param templateDir Template position 
  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. Introduction of Examples

Use freemarker.jar to download it on your own google.

In this example, we will generate an HTML file by Freemarker, including the head and tail of html, already body. These three parts will correspond to three template files respectively, as follows:

To output a result set within a template, ${} can be output using an EL-like expression

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/Update Footer.do"> Update Footer</a>

body.ftl, this template include s the above two template files

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  2. <html>  
  3.   <head>  
  4.     <title>User List</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="#">User List </a> <br/>"
  22.   <table border="1">  
  23.     <tr>  
  24.         <td>User name</td>  
  25.         <td>Age</td>  
  26.         <td>Birthday</td>  
  27.         <td>id</td>  
  28.         <td>operation</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}">Delete</a></td>
  39.         </tr>  
  40.     </#list>  
  41.       
  42.   </table>  
  43. <hr/>  
  44.   <#include "footer.ftl" parse=true encoding="utf-8">  
  45.   </body>  
  46. </html>  

Three entity classes corresponding to the three templates

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. }  

The following template contains some business logic operations for these three entity classes

  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("Beijing-Langfang-Good company!!!! Wow ha ha!!!");  
  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("Beijing Chaoyang CBD");  
  14.         h.setCompanyName("Shanghai Tangxiu!!!");  
  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. }  

The above is mainly the template for some of your business and dao layer operations, so there is no database operations involved, mainly for experiments.

The method of generating html external calls will use the class FreeMarkertUtil, which has been given above.

  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.      * Call FreeMarkertUtil.java 
  26.      * FreeMarkertUtil.processTemplate("body.ftl", root, out); 
  27.      * To generate html files 
  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. }  
At this point, I will provide a servlet to call the ProcessClient to generate the html page when the client makes the first request, and then every time I visit it, I can directly access the html to make it truly static.

  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.         //The path to store after html generation  
  42.         String dirPath = request.getSession().getServletContext().getRealPath("/templates/html");  
  43.         File path = new File(dirPath);  
  44.         //Name of the generated file  
  45.         String indexFileName = "index.html";  
  46.         /** 
  47.          * To determine whether the html file already exists, access html directly if it exists, and generate html file does not exist 
  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.             //Generate html files  
  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.      * Initialize the template configuration for later acquisition, and load it in init mainly to ensure that the Configuration instance is unique 
  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 configuration

  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>Template storage location is based on app Root directory  
  8.     <param-value>/templates</param-value>  
  9.    </init-param>  
  10.    <load-on-startup>3</load-on-startup>Initialize template configuration for startup  
  11.  </servlet>  
  12.   
  13.  <servlet-mapping>  
  14.    <servlet-name>Index</servlet-name>  
  15.    <url-pattern>/Index.do</url-pattern>  
  16.  </servlet-mapping>  

Deploy to tomcat, enter: http://localhost/htmlpage/Index.do

Page effect:

The page is ready, but the content has changed, how to update it? I am here when the list content changes, I delete the original html, use the template and then regenerate the HTML page that conforms to the new results.

When I delete a page, I will regenerate the html page, but because of the browser cache, that is, you deleted and regenerated the new html page, but the browser still saved the original page, not refreshed twice.

When I don't update the html, I will rename it so that the browser can load the latest html.

The specific deletion operations are as follows:

  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.     //delete user  
  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.         //Location of html generation  
  38.         String dirPath = request.getSession().getServletContext().getRealPath("/templates/html");  
  39.         //File name  
  40.         String indexFileName = "index.html";  
  41.           
  42.         //Delete the original file  
  43.         delOldHtml(dirPath,indexFileName);  
  44.           
  45.         //Prevent browser caching for regenerating new 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.      * Delete the original html file 
  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. }  

With the above operation, every time html is updated, the problem of browser caching can not be solved.

Another tool class that needs to be introduced is the java class that determines whether a specific html file has been generated

  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.        //Test whether the specified file should be included in a list of files.  
  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. }  

At this point, the whole static is completed. The static update mechanism is customized according to the business of your own project. It can generate html files regularly or manually.

The project structure chart is as follows:


Remember: not all pages of a website need to be static, mainly some data pages with low real-time performance need to be static (to improve access speed), others are achieved through pseudo-static, that is, to rewrite utl.

Page static is not the only way to improve the performance of the website, but also can be achieved by some caching products.


Common FreeMarker Resources

Official website home page: http://www.freemarker.org/

Eclipse plug-in JbossTool: http://www.jboss.org/tools/download/

Chinese Documents: https://sourceforge.net/projects/freemarker/files/chinese-manual/FreeMarker_Manual_zh_CN.pdf/download

Posted by jburbage on Fri, 28 Jun 2019 15:21:04 -0700