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


freemarker java方法 调用 freemarker实现原理_user



一、 创建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:代表用户请求的上下文路径.

 

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

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处理中使用,会在后面的专门章节中讲