Freemarker原理解析

来源:互联网 发布:记账软件onlinedown 编辑:程序博客网 时间:2024/06/05 06:13

FreeMarker生成静态页原理
      FreeMarker适合于作为Web应用的表现层。freemarker大致原理是:将页面中所需要的样式放入FreeMarker文件中,然后将页面所需要的数据动态绑定,并放入Map中,通过调用FreeMarker模板文件解析类process()方法完成静态页面的生成。了解了上面的原理,接下来我就一步 步带您实现FreeMarker生成静态页面。


一、 创建FreeMarker模板文件user.ftl
User.ftl
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv=Content-Type content="text/html; charset=utf-8">
    <title>user.ftl</title>
  </head>
  <body>
    ${user.userName}
    ${user.userPassword}

  </body>
</html>
二、 创建FreeMarker模板文件动态绑定的数据对象类User.java(Sring中pojo)
User.java
//..省略包的导入
      public class User{
 private String userName;
private String userPassword;
…省略getter()与setter方法

}

三、 创建FreeMarker模板文件解析器类FreeMarkertUtil
FreeMarkertUtil.java
//省略包的导入
Public class FreeMarkerUtil{
//templatePath模板文件存放路径
//templateName 模板文件名称
//filename 生成的文件名称

public static void analysisTemplate(String templatePath,String templateName,String fileName,Map<?,?>root){
try {
   Configuration config=new Configuration();
  //设置要解析的模板所在的目录,并加载模板文件
  config.setDirectoryForTemplateLoading(new File(templatePath));
   //设置包装器,并将对象包装为数据模型
   config.setObjectWrapper(new DefaultObjectWrapper());
  //获取模板,并设置编码方式,这个编码必须要与页面中的编码格式一致
 //否则会出现乱码
Template template=config.getTemplate(templateName,“UTF-8”);
   //合并数据模型与模板
   FileOutputStream fos = new FileOutputStream(fileName);
   Writer out = new OutputStreamWriter(fos,“UTF-8”);
      template.process(root, out);
      out.flush();
      out.close();
  } catch (IOException e) {
   e.printStackTrace();
  }catch (TemplateException e) {
   e.printStackTrace();
  }
 }
}

四、 创建FreeMarker生成静态页面测试类ClientTest.java
//..省略包的导入
public class ClientTest{
 public static void main(String[] args){
  User user=new User();
  user.setUserName("张三");
  user.setUserPassword("123");
  Map<String,Object> root=new HashMap<String, Object>();
  root.put("user", user);

  String templatesPath="D:/DevPlateForm/Eclipse/workspaces/freeMakerTest/src/templates";
  String templateFile="/user.ftl";
  String htmlFile=templatesPath+"/user.html";
    FreeMarkertUtil.analysisTemplate(templatesPath,templateFile,htmlFile,root);
}
}
注意: templatesPath为我机器上的FreeMarker模板文件存放路径。如果您要是测试的话,可以将此改为您创建的模板文件存放路径。好了,所有的工作都已经完成了,我们可以运行ClientTest类来测试了。
 本例在您的工程中运行时,必须导入freemarker.jar文件,否则不能编译。
 在我的工程中,您可以找到对应的文件。

 

五。freemarker变量值的获取

在Struts2框架下,Struts2框架充当了之前的Servlet角色,只要浏览器的请求经过Struts2处理后,Struts2都会自动加载FreeMarker模板,并使用数据模型来填充该模板,再将最后的HTML页面输出给客户端

Struts2解析FreeMarker模板中变量的顺序如下:
 1,FreeMarker模板内建的变量;
 2,ValueStack中的变量;
 3,ActionContext中的变量;
 4,HttpServletRequest中的属性;
 5,HttpSession中的属性;
 6,ServletContext范围的属性.

FreeMarker模板的内建变量有如下几个:
 1,stack:代表ValueStack本身,可通过如下方式来访问其中的变量"${stack.findString('ognl expr')}"
 2,action:代表刚刚执行过的Action实例
 3,response:代表HpptServletResponse实例
 4,res:代表HpptServletResponse实例
 5,request:代表HpptServletRequest实例
 6,req:代表HpptServletRequest实例
 7,session:代表HpptSession实例
 8,application:代表ServletContext实例
 9,base:代表用户请求的上下文路径.

 

六. 数据模式+模板=输出

      这些例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码是FreeMarker的指令,而包含FreeMarker的指令的文件就称为模板(Template)。
     至于user.name和latestProduct.name来自于数据模型(data model)。数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成。模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型。

 1、下面是一个可能的数据模型:
(root)
  |
  +- user = "Big Joe"
  |
  +- latestProduct
      |
      +- url = "products/greenmouse.html"
      |
      +- name = "green mouse"
数据模型类似于计算机的文件系统,latestProduct可以看作是目录。

2、数据模型
(1)基础
在快速入门中介绍了在模板中使用的三种基本对象类型:scalars、hashes 和sequences,其实还可以有其它更多的能力:
scalars:存储单值
hashes:充当其它对象的容器,每个都关联一个唯一的查询名字
sequences:充当其它对象的容器,按次序访问

方法:通过传递的参数进行计算,以新对象返回结果
用户自定义FTL标记:宏和变换器

通常每个变量只具有上述的一种能力,但一个变量可以具有多个上述能力,如下面的例子:
(root)
 |
 +- mouse = "Yerri"
     |
     +- age = 12
     |
     +- color = "brown"> 
mouse既是scalars又是hashes,将上面的数据模型合并到下面的模板:
${mouse}       <#-- use mouse as scalar -->
${mouse.age}   <#-- use mouse as hash -->
${mouse.color} <#-- use mouse as hash --> 
输出结果是:
Yerri
12
brown 

(2)Scalar变量
Scalar变量存储单值,可以是:
字符串:简单文本,在模板中使用引号(单引号或双引号)括起
数字:在模板中直接使用数字值
日期:存储日期/时间相关的数据,可以是日期、时间或日期-时间(Timestamp);通常情况,日期值由程序员加到数据模型中,设计者只需要显示它们
布尔值:true或false,通常在<#if …>标记中使用

(3)hashes 、sequences和集合
有些变量不包含任何可显示的内容,而是作为容器包含其它变量,者有两种类型:
hashes:具有一个唯一的查询名字和它包含的每个变量相关联
sequences:使用数字和它包含的每个变量相关联,索引值从0开始
集合变量通常类似sequences,除非无法访问它的大小和不能使用索引来获得它的子变量;集合可以看作只能由<#list …>指令使用的受限sequences

(4)方法
方法变量通常是基于给出的参数计算值。
下面的例子假设程序员已经将方法变量avg放到数据模型中,用来计算数字平均值:
The average of 3 and 5 is: ${avg(3, 5)}
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
The average of the price of python and elephant is:
    ${avg(animals.python.price, animals.elephant.price)}

(5)宏和变换器
宏和变换器变量是用户自定义指令(自定义FTL标记),会在后面讲述这些高级特性

(6)节点
节点变量表示为树型结构中的一个节点,通常在XML处理中使用,会在后面的专门章节中讲

转自:http://aixiangct.blog.163.com/blog/static/915224612011413104313441/