FreeMark是一个模板框架,它有自己的一套模板语言,整个框架的内核主要集中在两个包当中,其它包当中的类主要工具类或是扩充类,这两个核心的包是freemark.core与freemark.template:
A.freemark.core包
这是框架的内核,它提供了框架的语言级支持,它所做的工作类似于ognl的主体工作,因为它两个工具都具有自己独立的语法,因为它们都需要构建自己的语法树,以及语法树中所种类型结点的定义,这个包的核心工具就是构建语法树,对整个框架提供了最底层的支持,如果没有它整个框架就不存在了。整个包的结构主要分为两大体系:一类是表达试(类似于java中的表达式);另一类是模板元素(类似于java中的关键字)它主要体现了一种语言的两个方面,最典型的两个方面。这两个类的关系是freemark.core.Expression(以下简称Expression)与freemark.core.TemplateElement(以下简称Element)它们有一个共同的基类就是freemark.core.TemplateObject,Expression的主要任务是完成一个表达式的解析并将一个表达试与一个数据模型TemplateMode联系起来;Element主要任务是完成freemark指令的解析,当然在指定解析的过程中需要有Expression的支持,因为通常一个指定都包含有相关的表达式。Expression与Element代表了freemark语法的两个重要方面,这两个方面相对独立,但又彼此联系,在这两个分支当中有几个需要注意的部分:
Expression内建语法(Build in):它是在一个freemark表达式后跟一个?来表达这种语法的,在?之后跟了一个名称,这个名称是一个被注册过的内建表达式对象,这些对象都继承自freemark.core.BuildIn类,而这个类又继承自Expression,一个BuildIn的作用就是将它之前的表达式进行修正和转换,比如之前的表达是一个字符串类型,我希望将它的第一个字母变成大写,这就是需要对前面表达式的结果进行修正转换,虽然这里为程序员提供了一个修正结果的接口,但是在一个模板页面上似乎没有提供注册的方式。
Element提供了两种扩充用户指令的方式:一种是通过页面宏的方式,另外一种是通过实现指定数据数据模型的方式即实现freemark.template.TemplateDirectiveModel或者是freemark.template.TemplateTransformModel(现在已经不被推荐使用)通过这两种方式都可以实现自己的方法库
B. freemark.template包
主要用来完成freemark数据模型的抽象,freemark框架采用的模式就是模板+数据=输出,而这里数据不是一般的数据它必须是实现了freemark.template.TemplateModel的数据,此包主要就是构建这种数据模型的抽象体系结构。TemplateModel是框架内核采用的数据模型,尤其是在Expression中使用非常频繁,为什么要使用这样一种数据模型,而不是直接使用java即有的数据类型,我想主要考虑到框架的扩展性。在这个数据模型的抽象体系结构中主要有以下几种类型:
Scalars简单类型:主要有四种类型Boolean、Number、String、Date,这四种java的基本类型经过处理后就变成了freemark框架的四种基本类型
Containers容器类型:主要包括Hashes、Sequences、Collections,这三种java的容器类型经过处理生就变成了freemark框架的三种集合类型
Methods方法类型:这是有别于一般语言的一种类型,Expression中的可以含有方法调用,但它并不是一个真正意义下的调用,在内部这个方法调用将被解析成一种类型即方法类型,最终方法类型计算的结果是调用此类型规定接口方法所计算的结果
Directives指定类型:此类型也是freemark比较特别的类型,这种类型将freemark的指令与它的数据模型进行了联系,关于此类型的说明在上面已经论述过了,需要注意一点的是实现这种类型的时候方法一定要是无状态的一个指令类型对象可能同时被多个线程访问
Node variables结点类型:这种类型主要用来包装一个树上的结点,此种类型主要用在处理xml文档的时候特别有用
Object wrappers包装类型:这种类型并不是freemark所使用的一种数据模型,而是用来产生freemark所需要的数据类型一个包装类型,也就是说给它任何一个java中的数据类型,它都可以包装出freemark中所需要的一种数据,所以在大多数据情况下我们并不需要直接提供一个TemplateModel对象,而是直接使用中的数据类型仍然可以freemark内核进行沟通的原因就在于此
下面具体对freemark的语法进行详细说明:
1 Freemark的数据类型
在前面的讨论中已经对freemark所采用的数据模板进行了分析,数据类型基本就是与它是对应的,这里再对这几种类型进行一次说明:
Scalars(基本型):String、Number、Boolean、Date
Containers(容器):Hash、Sequence、Collection
Subroutines(子程序):在前已经谈到了方法类型与指令类型,这里在对这种子程序类型进行一下深入的分析。在freemark中的子程序类型实际上分得情况比较多,彼此之间有差别但又有联系,子程序主要分为以下几种:一种是Macro类型(具体还分为两种类型一类叫Macro另一类叫function)这种类型主要由模板页面中的<#Macro指令与<#function指令生成;一种是由实现了TemplateMethodModel接口对象叫做方法;一种是由实现TemplateDirectiveModel接口的对象叫做指令。如果将第一种类型分成两种类型第一类叫Macro;第二类叫Function;第三类叫Method;第四叫Directive。那这四类都可以称之为子程序类型,并且这四类有着不同寻常的关系,关系非常的具有美感。Macro与Function在模板中通过指令生成;Method与Directive通过在代码中实现接口生成;Function与Method属于Expression体系(只可以在表达式中进行调用);Macro与Directive属于Element体系(只能以用户自定义指令的形式进行调用);从定义形式上讲Macro与Function可列为一组,而Method与Directive可列为另一组;从调用形式与效果上讲Macro与Directive可列为组,而Function与Method可列为另一组;Macro与Directive被统一成了一个UnifiedCall对象,而Method与Function被统一成了一个MethodCall对象。
Node(树结点类型):这种类型主要是为了处理xml文件而产生的
2 模板语法
Freemark模板语法主要有指令、表达式、插值
指令:指令分为两种,一种是预定义指令,另一种是自定义指令。对于预定义指定一般开始标记为<#指令名称 指令参数>,结束标记为</#指令名称>,如果对于一个预定义的指令没的标签体内容,则它没有结点标签,例如:<#include 内容>,这里要特别注意,这个没有标签体的标签没有“/>”结束符,而是直接以“>”结束。关于这点它与自定义指令有一些差别,自定义指令以@代替#,但是如果没有标签体,自定义指令的写法应该为:<@mydirective something />
表达式:
n 指定直接值
u Strings: "Foo" or 'Foo' or "It's \"quoted\"" or r"C:\raw\string"
u Numbers: 123.45
u Booleans: true, false
u Sequences: ["foo", "bar", 123.45], 1..100
u Hashes: {"name":"greenmouse", "price":150}
n 获取变量值
u Top-level variables: user
u Retrieving data from a hash: user.name, user["name"]
u Retrieving data from a sequence: products[5]
u Special variable: .main
n 字符串操作
u Interpolation (or concatenation): "Hello${user}!" (or "Free"+"Marker")
u Getting a character: name[0]
n 序列操作
u Concatenation: users + ["guest"]
u Sequence slice: products[10..19] or products[5..]
n 散列值操作
u Concatenation: passwords + {"joe":"secret42"}
n 算术计算: (x * 1.5 + 10) / 2 - y % 100
n 比较: x==y, x!=y, x<y, x>y, x>=y, x<=y, x<y, ...etc.
n 逻辑操作: !registered && (firstVisit || fromEurope)
n 内建操作: name?upper_case
n 方法调用: repeat("What", 3)
n 缺失值控制操作:
u 默认值: name!"unknown" or (user.name)!"unknown" or name! or (user.name)!
u 缺失测试: name?? or (user.name)??
n 括号
n 表达式中的空白
n 操作符优先级
插值:${表达式},插值主要被使用在两个场合,一种是在文本区域中使用,例如<h1>hello${name};另一种是字符串字面量内嵌插值,例如<#include “/footer/${company}.html” >,一般第二种形式尽量少使用,因为它可以用字符串的加运算来取代,另外在指令中的表达式也要尽量避免使用插值形式,虽然可以使用,但一般意义不是很而且还容易出错
分享到:
相关推荐
1. **分析XML文件**:打开生成的XML文件,仔细查看其结构。注意观察哪些部分需要被动态填充数据。 2. **标记需要动态填充的数据**:使用FreeMarker的语法标记需要被替换的数据位置。例如,可以使用`...
Freemarker是一个强大的Java模板引擎,它允许开发者使用模板语言来分离应用...这对于报告生成、数据分析或其他需要可视化的场景非常有用,因为它允许开发者将动态数据与专业设计的文档模板相结合,创建出高质量的输出。
#### 三、FreeMarker 实际应用案例分析 为了更好地理解 FreeMarker 如何应用于实际项目中,我们可以考虑以下几个场景: 1. **动态网页生成**: - 使用 FreeMarker 生成动态 HTML 页面,可以根据数据库中的数据...
在源码分析方面,Freemarker的核心概念包括模板、数据模型和Freemarker配置。模板是HTML或其他格式的文件,其中包含Freemarker表达式,这些表达式会在运行时被数据模型中的值替换。数据模型是应用程序提供的Java对象...
然后,分析源码中的类和方法,理解它们如何结合Apache POI和Freemarker来处理Word文档。同时,你可以通过调试和运行代码,观察动态生成的Word文档效果,以加深对Java处理Word文档和Freemarker模板引擎的理解。
在Word文档中生成统计图是一项常见的需求,尤其在数据分析和报告制作时。本篇文章将深入探讨两种方法,教你如何利用FreeMarker来实现这一功能。 ### 一、生成图片在客户端放入Word文档 1. **生成统计图**: 首先,...
源码分析: `freemarker-2.3.19.tar.gz` 包含的是Freemarker 2.3.19版本的源代码。通过阅读源码,开发者可以了解到Freemarker如何解析模板、执行表达式、处理变量和指令、以及如何与Java对象模型交互等核心机制。...
在IT行业中,Ant、FreeMarker和Apache POI是三个非常重要的工具,它们分别在构建自动化、模板引擎和处理Microsoft Office文档方面发挥着关键作用。在这个"ant + freemarker + excel解析"的主题中,我们将深入探讨这...
- 模板设计上,可以使用Freemarker的文本、段落、列表等指令创建Word文档的结构,用`<#assign>`和`<#if>`等控制流语句处理条件和循环。 - 在Java代码中,创建`Document`对象,加载模板,设置字体、字号等样式,...
在IT行业中,数据导出是常见的需求之一,尤其是在数据分析、报告生成或数据交换的场景下。本案例聚焦于使用FreeMarker模板引擎将后台返回的list集合数据导出到Word表格中,这种技术常用于动态生成文档,使得内容可...
day09_FreeMark入门_静态化页面标签介绍_静态化页面实现 day10_Nginx代理详解..单点登录系统工程搭建_接口文档讲解 day11_单点登录系统实现_用户名回显_cookie跨域问题详解 day12 day13 17品优购电商系统...