🎶 Sym - 一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)平台

📕 思源笔记 - 一款桌面端笔记应用,支持 Windows、Mac 和 Linux

🎸 Solo - B3log 分布式社区的博客端节点,欢迎加入下一代社区网络

♏ Vditor - 一款浏览器端的 Markdown 编辑器

FreeMarker 使用入门及静态页面的生成

在编写静态页面的时候,往往 header,nav, footer,side 部分是通用的。 最重要的是:此时,如果你是根据 Fireworks 或者 Photoshop 来进行编写,那么文案、链接等很多东西都是不确定,这样就会导致频繁的修改。如果页面一多,且修改的是通用部分。那么你麻烦了,至于啥麻烦,你懂的!

为了避免这样的情况发生,你可以使用一些模版引擎来解决这样的问题。在此,我就给大家介绍一下我所使用的模版引擎吧。

模版引擎:FreeMarker

开发工具:NetBeans

步骤:

1. 新建一个 Maven Web Application

2. 找到 pom.xml 添加依赖和构建插件

<dependencies>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.20</version>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.mortbay.jetty&lt;/groupId&gt;
            &lt;artifactId&gt;maven-jetty-plugin&lt;/artifactId&gt;
            &lt;version&gt;6.1.22&lt;/version&gt;
            &lt;configuration&gt;
                &lt;connectors&gt;
                    &lt;connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"&gt;
                        &lt;port&gt;8084&lt;/port&gt;
                    &lt;/connector&gt;
                &lt;/connectors&gt;  
                &lt;stopKey&gt;stop&lt;/stopKey&gt;
                &lt;stopPort&gt;4501&lt;/stopPort&gt;
                &lt;webAppConfig&gt;
                    &lt;contextPath&gt;/&lt;/contextPath&gt;
                &lt;/webAppConfig&gt;
                &lt;scanIntervalSeconds&gt;1&lt;/scanIntervalSeconds&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.3.2&lt;/version&gt;
            &lt;configuration&gt;
                &lt;source&gt;1.6&lt;/source&gt;
                &lt;target&gt;1.6&lt;/target&gt;
                &lt;compilerArguments&gt;
                    &lt;endorseddirs&gt;${endorsed.dir}&lt;/endorseddirs&gt;
                &lt;/compilerArguments&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.1.1&lt;/version&gt;
            &lt;configuration&gt;
                &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-dependency-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.1&lt;/version&gt;
            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;phase&gt;validate&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;copy&lt;/goal&gt;
                    &lt;/goals&gt;
                    &lt;configuration&gt;
                        &lt;outputDirectory&gt;${endorsed.dir}&lt;/outputDirectory&gt;
                        &lt;silent&gt;true&lt;/silent&gt;
                        &lt;artifactItems&gt;
                            &lt;artifactItem&gt;
                                &lt;groupId&gt;javax&lt;/groupId&gt;
                                &lt;artifactId&gt;javaee-endorsed-api&lt;/artifactId&gt;
                                &lt;version&gt;6.0&lt;/version&gt;
                                &lt;type&gt;jar&lt;/type&gt;
                            &lt;/artifactItem&gt;
                        &lt;/artifactItems&gt;
                    &lt;/configuration&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;</pre>
  1. 修改 web.xml,配置 FreeMarker 和 请求解析的 servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>FreeMarkerTest</display-name>
    <welcome-file-list>  
        <welcome-file>/index.html</welcome-file>
    </welcome-file-list>
    <servlet>
        <servlet-name>freemarker</servlet-name>
        <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
        <!-- 下面配置FreeMarker的ftl文件位置 -->
        <init-param>
            <param-name>TemplatePath</param-name>
            <param-value>/</param-value>
        </init-param>
        <!-- 是否和服务器(tomcat)一起启动,0为不,1为是 -->
        <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>RequestServlet</servlet-name>
        <servlet-class>org.b3log.RequestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestServlet</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
</web-app>
  1. 编写解析类。通过 URL 访问时,就会对所访问的页面相应的生成一个静态页面。:由于 CSS 和 JS 的引入,在路径上需要保持一致,使得所生成的静态页面也能正确访问到 CSS 和 JS。
package org.b3log;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 页面渲染 & 静态页面生成.
 *
 * @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
 * @version 1.0.0.1, Jan 30, 2014
 */
public class RequestServlet extends HttpServlet {

    public RequestServlet() {
        super();
    }

    //负责管理FreeMarker模板的Configuration实例  
    private Configuration cfg = null;

    @Override
    public void init() throws ServletException {
        //创建一个FreeMarker实例  
        cfg = new Configuration();
        //指定FreeMarker模板文件的位置  
        cfg.setServletContextForTemplateLoading(getServletContext(), "/WEB-INF/view");
        cfg.setDefaultEncoding("UTF-8");
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //建立数据模型  
        Map root = new HashMap();

        // 模版处理
        String urlPath = request.getServletPath();
        Template t = cfg.getTemplate(urlPath.replace(".html", ".ftl"));
        t.setEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
        Writer writer = response.getWriter();
        try {
            t.process(root, writer);
        } catch (TemplateException ex) {
            Logger.getLogger(RequestServlet.class.getName()).log(Level.SEVERE, null, ex);
        }

        // 静态页面生成
        String genPath = "E:/working/b3log/src/main/webapp" + urlPath.replace("\\", "/");
        File flie = new File(genPath);
        File dir = new File(genPath.replaceAll("(/\\w*.html)", ""));
        if (!flie.exists()) {
            dir.mkdirs();
            flie.createNewFile();
        }
        
        OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(genPath), "UTF-8");
        try {
            t.process(root, out);
        } catch (TemplateException ex) {
            Logger.getLogger(RequestServlet.class.getName()).log(Level.SEVERE, null, ex);
        }
        out.flush();
        out.close();
    }

    @Override
    public void destroy() {
        super.destroy();
    }
}

5. 为了方便运行,在 Project Files 下添加 nbactions.xml,这样右键 Custom 中就可以选择 jetty-run 或者 jetty-debug 来运行程序了。

<?xml version="1.0" encoding="UTF-8"?>
<actions>
    <action>
        <actionName>CUSTOM-jetty-run</actionName>
        <displayName>jetty-run</displayName>
        <goals>
            <goal>jetty:run</goal>
        </goals>
    </action>
    <action>
        <actionName>CUSTOM-jetty-debug</actionName>
        <displayName>jetty-debug</displayName>
        <goals>
            <goal>jetty:run</goal>
        </goals>
        <properties>
            <jpda.listen>maven</jpda.listen>
        </properties>
    </action>
</actions>

6. 开始编写 FreeMarker 页面吧

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>B3log.org</title>
        <#include "../common/meta.ftl">
    </head>
    <body>
        <#include "../common/header.ftl">
        <div>
           hello, FreeMarker & static page!
        </div>
        <#include "../common/footer.ftl">
    </body>
</html> 

 最后附上项目目录结构


欢迎注册黑客派社区,开启你的博客之旅。让学习和分享成为一种习惯!

推荐阅读
留下你的脚步