`

FreeMarker使用教程

阅读更多
作者:永恒の_☆ 地址:http://blog.csdn.net/chenghui0317/article/details/7832474
一、Freemarker的介绍

    Freemarker 是一款模板引擎,是一种基于模版生成静态文件的通用 工具,它是为java程序员提供的一个开发包,或者说是一个类库,它不是面向最终用户的,而是为程序员提供了一款可以嵌入他们开发产品的应用程序。

    Freemarker 是使用纯java编写的,为了提高页面的访问速度,需要把页面静态化, 那么Freemarker就是被用来生成html页面。

    到目前为止,Freemarker使用越来越广泛,不光光只是它强大的生成技术,而且它能够与spring进行很好的集成。

    现在开始一层层揭开它的神秘面纱。。


二、Freemarker的准备条件

    freemarker.2.3.16.jar   下载地址:http://download.csdn.net/detail/ch656409110/4494067 (这个jar包其实在struts2里面)


三、Freemarker生成静态页面的原理

    Freemarker 生成静态页面,首先需要使用自己定义的模板页面,这个模板页面可以是最最普通的html,也可以是嵌套freemarker中的 取值表达式, 标签或者自定义标签等等,然后后台读取这个模板页面,解析其中的标签完成相对应的操作, 然后采用键值对的方式传递参数替换模板中的的取值表达式,做完之后 根据配置的路径生成一个新的html页面, 以达到静态化访问的目的。


四、Freemarker提供的标签

Freemarker提供了很多有用 常用的标签,Freemarker标签都是<#标签名称>这样子命名的,${value} 表示输出变量名的内容 ,具体如下:

1、list:该标签主要是进行迭代服务器端传递过来的List集合,比如:
[html] view plaincopyprint?

    <#list nameList as names>   
      ${names}  
    </#list> 

name是list循环的时候取的一个循环变量,freemarker在解析list标签的时候,等价于:

[java] view plaincopyprint?

    for (String names : nameList) { 
        System.out.println(names); 
    } 

2、if:    该标签主要是做if判断用的,比如:

[html] view plaincopyprint?

    <#if (names=="陈靖仇")> 
     他的武器是: 十五~~ 
    </#if> 

这个是条件判断标签,要注意的是条件等式必须用括号括起来, 等价于:

[java] view plaincopyprint?

    if(names.equals("陈靖仇")){ 
        System.out.println("他的武器是: 十五~~"); 
    } 


3、include:该标签用于导入文件用的。

[html] view plaincopyprint?

    <#include "include.html"/> 

这个导入标签非常好用,特别是页面的重用。

另外在静态文件中可以使用${} 获取值,取值方式和el表达式一样,非常方便。

下面举个例子(static.html):

[html] view plaincopyprint?

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
    <html> 
    <head> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
    <title>Insert title here</title> 
    </head> 
    <body> 
     
    描述:${description} 
    <br/> 
    集合大小:${nameList?size} 
    <br/> 
    迭代list集合: 
    <br/> 
    <#list nameList as names> 
    这是第${names_index+1}个人,叫做:<label style="color:red">${names}</label> 
    if判断: 
    <br/> 
    <#if (names=="陈靖仇")> 
     他的武器是: 十五~~ 
    <#elseif (names=="宇文拓")>       <#--注意这里没有返回而是在最后面-->  
     他的武器是: 轩辕剑~· 
    <#else> 
    她的绝招是:蛊毒~~ 
    </#if> 
    <br/> 
    </#list> 
    迭代map集合: 
    <br/> 
    <#list weaponMap?keys as key> 
    key--->${key}<br/> 
    value----->${weaponMap[key]!("null")} 
    <#--  
    fremarker 不支持null, 可以用! 来代替为空的值。 
    其实也可以给一个默认值   
    value-----${weaponMap[key]?default("null")} 
    还可以 在输出前判断是否为null 
    <#if weaponMap[key]??></#if>都可以 
    --> 
     
    <br/> 
    </#list> 
    include导入文件: 
    <br/> 
    <#include "include.html"/> 
     
    </body> 
    </html> 

实际代码:

[java] view plaincopyprint?

    package com.chenghui.test; 
     
    import java.io.File; 
    import java.io.FileOutputStream; 
    import java.io.IOException; 
    import java.io.OutputStreamWriter; 
    import java.io.Writer; 
    import java.util.ArrayList; 
    import java.util.HashMap; 
    import java.util.List; 
    import java.util.Map; 
     
    import freemarker.template.Configuration; 
    import freemarker.template.DefaultObjectWrapper; 
    import freemarker.template.Template; 
    import freemarker.template.TemplateException; 
     
    public class CreateHtml { 
        public static void main(String[] args) { 
            try { 
                //创建一个合适的Configration对象 
                Configuration configuration = new Configuration(); 
                configuration.setDirectoryForTemplateLoading(new File("D:\\project\\webProject\\WebContent\\WEB-INF\\template")); 
                configuration.setObjectWrapper(new DefaultObjectWrapper()); 
                configuration.setDefaultEncoding("UTF-8");   //这个一定要设置,不然在生成的页面中 会乱码 
                //获取或创建一个模版。 
                Template template = configuration.getTemplate("static.html"); 
                Map<String, Object> paramMap = new HashMap<String, Object>(); 
                paramMap.put("description", "我正在学习使用Freemarker生成静态文件!"); 
                 
                List<String> nameList = new ArrayList<String>(); 
                nameList.add("陈靖仇"); 
                nameList.add("玉儿"); 
                nameList.add("宇文拓"); 
                paramMap.put("nameList", nameList); 
                 
                Map<String, Object> weaponMap = new HashMap<String, Object>(); 
                weaponMap.put("first", "轩辕剑"); 
                weaponMap.put("second", "崆峒印"); 
                weaponMap.put("third", "女娲石"); 
                weaponMap.put("fourth", "神农鼎"); 
                weaponMap.put("fifth", "伏羲琴"); 
                weaponMap.put("sixth", "昆仑镜"); 
                weaponMap.put("seventh", null); 
                paramMap.put("weaponMap", weaponMap); 
                 
                Writer writer  = new OutputStreamWriter(new FileOutputStream("success.html"),"UTF-8"); 
                template.process(paramMap, writer); 
                 
                System.out.println("恭喜,生成成功~~"); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } catch (TemplateException e) { 
                e.printStackTrace(); 
            } 
             
        } 
    } 

附:freemarker教程

    这样子基本上可以算的上可以简单的去做一点简单的生成了,但是要在实际中去运用,还是差的很远的,因为freemarker给的标签完全满足不了我们的需要,这时候就需要自定义标签来完成我们的需求了。。
五、Freemarker自定义标签

Freemarker自定义标签就是自己写标签,然后自己解析,完全由自己来控制标签的输入输出,极大的为程序员提供了很大的发挥空间。

基于步骤:

       以前写标签需要在<后加# ,但是freemarker要识别自定义标签需要在后面加上@,然后后面可以定义一些参数,当程序执行template.process(paramMap, out);,就会去解析整个页面的所有的freemarker标签。

     自定义标签 需要自定义一个类,然后实现TemplateDirectiveModel,重写execute方法,完成获取参数,根据参数do something等等。。

    将自定义标签与解析类绑定在一起需要在paramMap中放入该解析类的实例,存放的key与自定义标签一致即可。。

    注意:在自定义标签中,如果标签内什么也没有,开始标签和结束标签绝对不能再同一行,不然会报错 freemarker.log.JDK14LoggerFactory$JDK14Logger error

  我曾经上当过,这是freemarker 存在的bug。

下面是static.html的例子:

[html] view plaincopyprint?

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
    <html> 
    <head> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
    <title>Insert title here</title> 
    </head> 
    <body> 
    <#--自定义变量--> 
    <#assign num='hehe'/> 
    ${num} 
    <br/> 
    自定义标签 
      <@content name="chenghui" age="120"> 
        ${output} 
        ${append} 
      </@content> 
       
    </body> 
    </html> 


下面是上面的static.html模板的解析类:

[java] view plaincopyprint?

    package com.chenghui.test; 
     
    import static freemarker.template.ObjectWrapper.DEFAULT_WRAPPER; 
     
    import java.io.IOException; 
    import java.io.Writer; 
    import java.util.Map; 
     
     
    import freemarker.core.Environment; 
    import freemarker.template.TemplateDirectiveBody; 
    import freemarker.template.TemplateDirectiveModel; 
    import freemarker.template.TemplateException; 
    import freemarker.template.TemplateModel; 
    import freemarker.template.TemplateModelException; 
    import freemarker.template.TemplateNumberModel; 
    import freemarker.template.TemplateScalarModel; 
     
    /**
     * 自定义标签解析类
     * @author Administrator
     *
     */ 
    public class ContentDirective implements TemplateDirectiveModel{ 
     
        private static final String PARAM_NAME = "name"; 
        private static final String PARAM_AGE = "age"; 
         
        @Override 
        public void execute(Environment env, Map params,TemplateModel[] loopVars, 
                TemplateDirectiveBody body) throws TemplateException, IOException { 
            if(body==null){ 
                throw new TemplateModelException("null body"); 
            }else{ 
                String name = getString(PARAM_NAME, params); 
                Integer age = getInt(PARAM_AGE, params); 
                //接收到参数之后可以根据做具体的操作,然后将数据再在页面中显示出来。 
                if(name!=null){ 
                    env.setVariable("output", DEFAULT_WRAPPER.wrap("从ContentDirective解析类中获得的参数是:"+name+", ")); 
                } 
                if(age!=null){ 
                    env.setVariable("append", DEFAULT_WRAPPER.wrap("年龄:"+age)); 
                } 
                Writer out = env.getOut(); 
                out.write("从这里输出可以再页面看到具体的内容,就像document.writer写入操作一样。<br/>"); 
                body.render(out); 
                 
                /*
                如果细心的话,会发现页面上是显示out.write()输出的语句,然后再输出output的内容,
                可见 在body在解析的时候会先把参数放入env中,在页面遇到对应的而来表单时的才会去取值
                但是,如果该表单时不存在,就会报错,  我觉得这里freemarker没有做好,解析的时候更加会把错误暴露在页面上。
                可以这样子弥补${output!"null"},始终感觉没有el表达式那样好。
                */ 
            } 
        } 
         
        /**
         * 获取String类型的参数的值
         * @param paramName
         * @param paramMap
         * @return
         * @throws TemplateModelException
         */ 
        public static String getString(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{ 
            TemplateModel model = paramMap.get(paramName); 
            if(model == null){ 
                return null; 
            } 
            if(model instanceof TemplateScalarModel){ 
                return ((TemplateScalarModel)model).getAsString(); 
            }else if (model instanceof TemplateNumberModel) { 
                return ((TemplateNumberModel)model).getAsNumber().toString(); 
            }else{ 
                throw new TemplateModelException(paramName); 
            } 
        } 
         
        /**
         * 
         * 获得int类型的参数
         * @param paramName
         * @param paramMap
         * @return
         * @throws TemplateModelException 
         */ 
        public static Integer getInt(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{ 
            TemplateModel model = paramMap.get(paramName); 
            if(model==null){ 
                return null; 
            } 
            if(model instanceof TemplateScalarModel){ 
                String str = ((TemplateScalarModel)model).getAsString(); 
                try { 
                    return Integer.valueOf(str); 
                } catch (NumberFormatException e) { 
                    throw new TemplateModelException(paramName); 
                } 
            }else if(model instanceof TemplateNumberModel){ 
                return ((TemplateNumberModel)model).getAsNumber().intValue(); 
            }else{ 
                throw new TemplateModelException(paramName); 
            } 
        } 
    } 

然后再前面的实际代码中加上:
[java] view plaincopyprint?

    //自定义标签解析 
    paramMap.put("content", new ContentDirective()); 

这样子基本上可以使用,freemarker完成自定义标签了,解决一写简单的业务逻辑, 但是在实际的项目中不可能这样子去做,因为还没有和spring进行集成使用,每次都需要在解析的时候把解析类的实例放进去。。
分享到:
评论

相关推荐

    freemarker操作手册-完整freemarker教程

    通过阅读《freemarker操作手册》提供的完整教程,你可以系统地学习到以上所有内容,并结合实践,熟练掌握Freemarker的使用技巧。无论是初学者还是经验丰富的开发者,这份手册都是深入理解和应用Freemarker不可或缺的...

    非常好的Freemarker中文教程

    从提供的文件名"FreeMarkerl_zh_CN.pdf"来看,这应该是一份中文版的Freemarker教程文档,对于中文使用者来说,阅读和学习起来会更加方便。通过详细研读这份教程,开发者不仅可以掌握Freemarker的基本使用,还能深入...

    FreeMarker设计指南.ppt

    这个“FreeMarker设计指南.ppt”文件很可能是关于如何有效地使用FreeMarker进行模板设计和编程的一份详细教程。以下是FreeMarker的一些核心知识点和相关概念: 1. **模板语言**:FreeMarker是基于文本的模板语言,...

    Freemarker2.3.16_带简单教程

    《Freemarker教程 中文版.pdf》是一个专门的教程,它可能包含以下内容: 1. **入门指南**:解释如何安装Freemarker,以及在Java项目中集成它的基本步骤。 2. **实例分析**:通过实际示例演示如何创建和使用模板,...

    FreeMarker实例教程,手把手教你FreeMarker的方方面面

    ### FreeMarker实例教程知识点详解 ...以上知识点覆盖了FreeMarker的主要方面,通过本教程的学习,读者不仅能够掌握FreeMarker的基本使用方法,还能够深入了解其高级特性,为日后解决复杂的Web开发问题打下坚实的基础。

    Freemarker教程(中文版)

    在“Freemarker教程+中文版.pdf”这份文档中,你将会详细了解到如何配置和初始化Freemarker,如何创建和解析模板,以及如何处理模板错误。教程还会深入讲解Freemarker的高级特性,如宏、指令、模板继承和布局等,...

    freemarker 教程 使用手册

    2. 数据模型设置:通过`ModelAndView`或`Map`将Java对象传递到视图,供Freemarker使用。 3. 视图解析:配置`ViewResolver`,例如`FreemarkerViewResolver`,确定模板路径和渲染逻辑。 四、Freemarker高级特性 1. ...

    freemarker\Freemarker教程_中文版

    为了使用Freemarker,开发者首先需要创建一个`Configuration`实例,并对其进行必要的配置。例如,设置模版的加载路径、数据模型的处理方式等。这一步骤确保了Freemarker能够正确地识别和处理模版。 ```java ...

    freemarker视频教程

    freemarker视频教程,绝对经典,欢迎大家下载,强烈推荐

    FreeMarker 中文教程 用于 FreeMarker 2.3.19

    ### FreeMarker 中文教程知识点概览 #### 一、FreeMarker 概述 - **定义与功能**:FreeMarker 是一款强大的、灵活的、可扩展的模板引擎,它支持多种编程语言,主要用于生成动态HTML页面以及其他格式的文档,如XML...

    freemarker教程下载

    本教程将深入探讨Freemarker的核心概念、主要功能以及如何在实际开发中有效地利用它。 1. **Freemarker基本概念** - **模板语言**:Freemarker使用模板语言来描述动态内容的结构和样式,与HTML类似但不完全相同,...

    FreeMarker教程pdf版

    ### FreeMarker教程精要 **FreeMarker** 是一种强大的模板引擎,主要用于生成动态网页或用于任何文本输出场景。本文档将深入探讨FreeMarker的核心组成部分及其使用方法,包括文本、注释、插值以及FTL(FreeMarker ...

    FreeMarker视频教程

    FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所...

    Freemarker使用手册、api、中文版教程

     Reference(FreeMarker 的参考文档,语言使用介绍) 中文翻译之所以选择 Programmer's Guide 是因为个人觉得该部分对如何实现 FreeMarker 进行了比较深入的阐述。有助于读者很好的了解其运作机制,以及去理解...

    FreeMarker手册-Freemarker 2.3.18

    在"FreeMarker手册.pdf"中,你将找到关于这些概念的详细解释、示例代码和最佳实践,对于深入理解和使用FreeMarker是非常有价值的资源。无论你是初学者还是经验丰富的开发者,这本手册都能为你提供必要的指导和支持。

    freemarker 2.3.18 中文手册

    这个2.3.18版本的中文手册是开发者学习和使用Freemarker的重要参考资料。 在Freemarker 2.3.18版本中,有几个关键知识点值得一提: 1. **模板语言基础**:Freemarker模板由静态文本和动态控制结构组成,如`&lt;#if&gt;`...

    Freemarker教程及jar包

    `Freemarker教程 中文版.pdf`是一份详细的中文教程,将指导你掌握以下关键知识点: 1. **模板设计模式**:了解如何定义模板的结构,包括基本的文本、注释、变量和表达式。 2. **控制结构**:学习如何使用条件语句...

    超完整FreeMarker中文教程,代码

    什么是FreeMarker? ................................................................................................. 7 我们应该阅读什么内容? .............................................................

    Freemarker语法规则教程

    ### Freemarker语法规则教程 #### 一、字符串格式化输出 在Freemarker中,字符串格式化是一项非常实用的功能,它可以将数据按照特定的格式进行输出,方便开发者控制最终的展示效果。以下是一些基本的例子: - **...

Global site tag (gtag.js) - Google Analytics