首页 > 代码库 > 对FreeMarker技术的思考

对FreeMarker技术的思考

        按照静态非静态来划分网页分为两种:静态网页和非静态网页,究其优缺点而言,静态网页在用户访问的时候响应快,但是由于里面的数据是写死的,所以致命的缺陷就是数据不能动态显示;非静态页面(如jsp)数据可以动态显示,可以这样理解,这样的页面就是显示数据的一个模板,但是由于在用户请求得到响应以前,服务器端需要将其解析为浏览器可识别的html语言,这个解析过程需要耗费时间(尤其页面数据量大的时候,耗费的时间会更多),所以致命的缺陷就是请求发出后响应的过程较慢。那么有没有一种方法或工具自动生成静态网页呢?答案是肯定的,今天谈一下对FreeMarker的认识:

        1、什么是FreeMarker:

        FreeMarker是一个用Java语言编写的模板引擎,通过模板(扩展名为“ftl”的文件)生成静态的网页,从而提高访问网站的用户体验。

        2、一般情况下什么时候使用FreeMarker:

        一般使用FreeMarker生成门户网站的静态文件。

        3、怎样使用FreeMarker:

        例子1:

        a、下载FreeMarker相关jar包:http://download.csdn.net/detail/wangshuxuncom/7592455

        b、新建所需要的模板——index.ftl:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr">
	<head>
		<title>首页</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
	</head>
	<body>
		<center style="margin-top: 21%;"><font style="color: red;font-size: 39pt;font-weight: bold;">${message}</font></center>
	</body>
</html>
        c、新建一个Servlet——IndexServlet:
package com.ghj.packageofservlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class IndexServlet extends HttpServlet {

	private static final long serialVersionUID = 1714787202664419914L;
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("message", "欢迎进入系统!!!");
        request.getRequestDispatcher("index.ftl").forward(request, response);
	}
}
        d、将FreeMarker相关jar包导入新建的系统中,并配置web.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<servlet>
		<servlet-name>freemarker</servlet-name>
		<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>

		<!-- FreemarkerServlet settings: -->
		<init-param>
			<param-name>TemplatePath</param-name><!-- 指定模板的路径 -->
			<param-value>/</param-value>
		</init-param>
		<init-param>
			<param-name>NoCache</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>ContentType</param-name><!-- 设置生成html文件的编码方式。 -->
			<param-value>text/html; charset=UTF-8</param-value>
		</init-param>

		<!-- FreeMarker settings: -->
		<init-param>
			<param-name>template_update_delay</param-name><!-- template_update_delay用来指定更新模版文件的间隔时间,相当于多长时间检测一下是否有必要重新加载模版文件,0 表示每次都重新加载,否则为多少毫秒钟检测一下模版是否更改。 -->
			<param-value>0</param-value>
		</init-param>
		<init-param>
			<param-name>default_encoding</param-name><!-- 设置模板文件的编码方式。 -->
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>number_format</param-name>
			<param-value>0.##########</param-value>
		</init-param>
		
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>freemarker</servlet-name>
		<url-pattern>*.ftl</url-pattern>
	</servlet-mapping>
	
	<servlet>
    	<servlet-name>IndexServlet</servlet-name>
    	<servlet-class>com.ghj.packageofservlet.IndexServlet</servlet-class>
  	</servlet>
  	<servlet-mapping>
    	<servlet-name>IndexServlet</servlet-name>
    	<url-pattern>/IndexServlet</url-pattern>
  	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>
        e、发布工程,在http中输入“http://127.0.0.1:8080/工程名/IndexServlet”即可看到效果;
        说明:在这个工程中,ftl文件充当了类似于jsp的角色。

        【0分下载该例子

        例子2:

        a、下载FreeMarker相关jar包:http://download.csdn.net/detail/wangshuxuncom/7592455

        b、新建所需要的模板——index.html(注意:非“ftl”):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr">
	<head>
		<title>首页</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
	</head>
	<body>
		<center style="margin-top: 21%;"><font style="color: red;font-size: 39pt;font-weight: bold;">${message}</font></center>
	</body>
</html>
        c、新建一个Servlet——IndexServlet:
package com.ghj.packageofservlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class IndexServlet extends HttpServlet {

	private static final long serialVersionUID = 1714787202664419914L;
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("message", "欢迎进入系统!!!");
        request.getRequestDispatcher("index.html").forward(request, response);//非“index.html”非“index.ftl”
	}
}
        d、将FreeMarker相关jar包导入新建的系统中,并配置web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<servlet>
		<servlet-name>freemarker</servlet-name>
		<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>

		<!-- FreemarkerServlet settings: -->
		<init-param>
			<param-name>TemplatePath</param-name><!-- 指定模板的路径 -->
			<param-value>/</param-value>
		</init-param>
		<init-param>
			<param-name>NoCache</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>ContentType</param-name><!-- 设置生成html文件的编码方式。 -->
			<param-value>text/html; charset=UTF-8</param-value>
		</init-param>

		<!-- FreeMarker settings: -->
		<init-param>
			<param-name>template_update_delay</param-name><!-- template_update_delay用来指定更新模版文件的间隔时间,相当于多长时间检测一下是否有必要重新加载模版文件,0 表示每次都重新加载,否则为多少毫秒钟检测一下模版是否更改。 -->
			<param-value>0</param-value>
		</init-param>
		<init-param>
			<param-name>default_encoding</param-name><!-- 设置模板文件的编码方式。 -->
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>number_format</param-name>
			<param-value>0.##########</param-value>
		</init-param>
		
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>freemarker</servlet-name>
		<url-pattern>*.html</url-pattern><!-- 非“*.ftl” -->
	</servlet-mapping>
	
	<servlet>
		<servlet-name>IndexServlet</servlet-name>
		<servlet-class>com.ghj.packageofservlet.IndexServlet</servlet-class>
  	</servlet>
  	<servlet-mapping>
		<servlet-name>IndexServlet</servlet-name>
		<url-pattern>/IndexServlet</url-pattern>
  	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>
    e、发布工程,在http中输入“http://127.0.0.1:8080/工程名/IndexServlet”即可看到效果;

        说明:在这个工程中,html文件充当了类似于jsp的角色;本例子和上面的代码基本一样,不同点在于:上一个例子模板的文件类型为ftl,而本例子为html——这说明一点:只要配置得当,模板未必只能是ftl类型的文件。

        【0分下载该例子

        总结:

        1、上面两个例子大同小异,看完上面例子之后大家可能会有疑问:上面两个例子中,从客户端请求的发出到客户端看到结果整个过程是怎样的呢?嗯嗯嗯,这确实是一个需要搞清楚的问题:向IndexServlet发出请求——>IndexServlet接收请求并将模板和模板所需数据作为响应——>FreemarkerServlet接收IndexServlet发出的请求并将数据“填充”到模板相应的位置,然后将响应返回客户端——>客户看到结果。

        2、个人感觉如果用FreeMarker单纯去实现上面的例子,认为有点儿大材小用,或者说有点儿“屈才”——如果要实现上面的功能,直接使用诸如jsp的非静态页面岂不不更好,FreeMarker的看家本事是生成诸如HTML格式的静态页面(且看下面例子)。

        例子3:

        a、下载FreeMarker相关jar包:http://download.csdn.net/detail/wangshuxuncom/7592455
        b、新建所需要的模板——index.ftl:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr">
	<head>
		<title>首页</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
	</head>
	<body>
		<center style="margin-top: 21%;"><font style="color: red;font-size: 39pt;font-weight: bold;">${message}</font></center>
	</body>
</html>

        c、新建一个创建HTML静态页面工具类——FreemarkerUtil:

package com.ghj.packageoftool;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Freemarker工具类
 * 
 * @author GaoHuanjie
 */
public class FreemarkerUtil {

    /** 
     * 创建静态HTML文件
     *
     * @param templateFilePath 模板文件存放的路径
     * @param templateFileName 模板文件名称
     * @param htmlFilePath 静态文件(即HTML文件)保存路径
     * @param htmlFileName 所生成静态文件(即HTML文件)的名称
     * @param propMap 用于处理模板的属性Object映射
     * 
     * @return boolean 静态文件创建成功返回true,否则返回false 
     */
    public boolean createHtmlFile(String templateFilePath, String templateFileName, String htmlFilePath, String htmlFileName, Map<String, Object> propMap){
        try {
        	Configuration configuration = new Configuration();
        	configuration.setDefaultEncoding("UTF-8");
            configuration.setDirectoryForTemplateLoading(new File(templateFilePath));
            //configuration.setClassForTemplateLoading(this.getClass(), "/ftl");//如果模板文件在src的某个包内,请将上一行代码注释掉而使用该代码,ftl代表包名。
            Template template = configuration.getTemplate(templateFileName, "UTF-8");//确保模板中的中文在生成静态文件中不变成乱码。
            File createHTMLFilePath = new File(htmlFilePath);
            if (!createHTMLFilePath.exists()) {//如果保存静态文件(即HTML文件)的根路径不存在,则创建该目录。
            	createHTMLFilePath.mkdirs();
            }
            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(htmlFilePath + "/" + htmlFileName)), "UTF-8"));//防止数据(propMap)中的中文在静态页面中变为乱码。
            template.process(propMap, writer);//生成静态文件 
            writer.flush();
            writer.close();
        } catch (TemplateException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
        	e.printStackTrace();
        	return false;
        } catch (Exception e) {
        	e.printStackTrace();
        	return false;
        }
        return true;
    }
}

        d、新建一个创建HTML静态页面监听器——CreatHtmlListener:

package com.ghj.packageoflistener;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import com.ghj.packageoftool.FreemarkerUtil;

/**
 * 创建HTML静态页面监听器
 * 
 * @author GaoHuanjie
 */
public class CreatHtmlListener implements ServletContextListener {  

    public void contextDestroyed(ServletContextEvent event) {
        //event.getServletContext().log("创建HTML静态页面监听器销毁!!!");
    }

    public void contextInitialized(ServletContextEvent event) {
    	FreemarkerUtil freemarkerUtil = new FreemarkerUtil();
    	String templateFilePath = event.getServletContext().getRealPath("/")+"templates";
    	String templateFileName = "index.ftl";
    	String htmlFilePath = event.getServletContext().getRealPath("/");
    	String htmlFileName = "index.html";
    	Map<String, Object> propMap = new HashMap<String, Object>();
    	propMap.put("message", "Hello,欢迎进入系统!!!");
    	if(freemarkerUtil.createHtmlFile(templateFilePath, templateFileName, htmlFilePath, htmlFileName, propMap)){
    		event.getServletContext().log("HTML静态页面创建完成!!!");
    	}
    }
}

        e、将FreeMarker相关jar包导入新建的系统中,并配置web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<listener>
        <listener-class>com.ghj.packageoflistener.CreatHtmlListener</listener-class>
    </listener>

	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
</web-app>

         f、发布工程,在http中输入“http://127.0.0.1:8080/工程名”即可看到效果;

        说明:在这个工程中,创建HTML静态页面的监听器在工程被Tomcat发布时被执行并且index.html被创建,在实际应用中某些门户网站生成静态页面的时机并不像该监听器写的那样——往往在监听器中添加一个定时器,在特定的时间点更新静态网页,以使客户端能够看到最新的内容,我不知道大家留意过没有,门户网站首页内容更新并不是那么的频繁。
        【0分下载该例子