该用户从未签到
|
一.Freemarker简介
0 N8 M' G1 `4 Q2 A; N9 B% s% m3 ]二.环境搭建与配置& t8 e9 N9 I$ L/ K; Y
三.常用语法
/ F. c1 D( r& x$ m C. m四.与struts结合5 W% g1 Q" [8 O) r8 h7 _7 e' _
五.生成Html页面
6 ~, x P3 ]- h+ W1 {, L# }$ t: Y% [0 `6 H
一.Freemarker简介5 }& E# N: m* h# l' S
什么是Freemarker:.
4 W4 K" g5 m, p! {Freemaker是一个”模板引擎”,也可以说是一个基于模板技术的生成文本输出的一个通用工具.它是一个java的包,一个JAVA程序员可以使用的
1 D, d- f$ A' W9 m6 P& p+ P类库.本身并不是一个对最终用户的应用程序.但是,程序员可以把它应用到他们的产品中.
' P [' e8 W2 w# s9 L1 l; FFreeMarker是设计为可以生成WEB PAGES.它是基于SERVLET遵循MVC模式的.这个思路是应用MVC模式要降低分离,网页设计人员和程序员的耦合.
0 L1 e4 d# N/ I" k" \2 S' j" k A0 A每个人都可以做他们擅长的工作.网页设计人员可以改变网页的面貌,而并不需要程序员的重新编译.因为业务逻辑和页面的设计已经被分离开了
- u; n& d& @4 Y.模板是不能由复杂的程序片断组成的.即便网页设计人员和程序员是一个人. 分离是有必要的.它能使程序更加的灵活和清晰.8 N* X; N% y' N" j9 ^2 Q; t
虽然Freemarker能编程,但是它并不是一个编程语言.它是为程序显示数据而准备的.(像数据库SQL语句的查询.)以及.Freemarker仅仅是利用模
{" `9 X8 i; Q g( W板加上数据生成文本页面./ _# B- ?1 B* v! T& M
Freemarker并不是一个WEB应用程序框架.可以说是一个WEB应用框架的一个组件.但是FREEMARKER引擎本身并不了解HTTP或者SERVLETS.它只不过
( c1 P/ U3 T, W生成文本而已.注意,它是MVC框架的一个组件(如STRUTS),也可以在模板中使用JSP标签.) {* O5 Q6 J& F5 C \
Freemarker下载地址为:http://www.freemarker.org/index.html9 R* s: n4 m3 N8 V8 U2 a
一般的用途:
& v# i1 ?+ W9 C' f0 ]2 Jl 能用来生成任意格式的文本:HTML,XML,RTF,JAVA源码,等等.9 u: r* p5 J n7 T3 X
l可以更好的嵌入到你的产品中,轻量级的.并不需要servlet环境.不依赖javax.servlet.classes.
( n V" B1 h' ?- x( cl可插入的模板读取器:你可以从任意的源码读取任意的模板.本地的文件,数据库等等.
( ], z* a- M- B( u" cl你可以做任意你想生成的文本.存储为本地文件.可以用来发送EMAIL或返回到WEB浏览器中.* r7 G$ Q$ [1 O
, K. o: o- ?* L7 N+ D) {0 Y
强大的模板语言$ J4 [$ K5 X6 O' C4 W* { _4 _; J
l完整的指令:include,if/elseif/else,loop.8 v+ Y7 w Z: |
l 建立和修改模板中的变量.3 u: q% Y# |+ r3 t4 \: W( S5 o! R: O8 j
l 能用复杂的表达式在任意地方指定变量.
: Y3 M" j1 _0 o0 a& J$ Ln字符串操作:concateration,sub-string,uppercase,capitalize,escaping.等等
7 t+ Z H4 _7 B1 yn十进制数学计算./ Q& H- Q$ |9 ^! Y" D$ B- O# o4 Z
n BOOL* _4 n5 B; j0 J5 c5 V
n读取数组和相关的数组元素.4 j0 Y% Y; S) B$ U# J. e
n可以自己添加特殊的计算方法.3 E7 E" a% i7 |. ? P
l宏指令3 J2 {; {* ?* ^0 \9 M; D' m& t
l 命名空间用来创建和维护宏指令库或者把大的项目分成许多模块.并不用担心命名冲突
! J1 E1 n/ I. _2 |4 N+ x: S二.环境搭建与配置
9 f/ U6 o: u5 O<!—freemarker初始配置-->
" O" `4 v/ {+ w L; N) e
- b5 }4 @* z: o' A+ Q<servlet>
: P* A0 Q; H( g0 M' e$ E N<servlet-name>freemarker</servlet-name>* k5 ~& w" w5 G0 r9 k% p
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
7 a Q) X8 Z6 \+ H! Z<init-param>
' G9 q4 K" }9 ?/ n% s<param-name>TemplatePath</param-name>
$ L1 T) V( R9 ?3 B" d<param-value>/</param-value>. G, ^2 \! G6 {/ ]! k. Q; O
</init-param>
( b0 c/ ?- D- n1 a<init-param>
; U6 _! T( _; Q" _<param-name>NoCache</param-name>
" a, R2 q# a. L; {<param-value>true</param-value>; r& n @4 n, _/ f( L7 m' x
</init-param>
% Z! |4 y0 E' B# b9 k# u<init-param>' H6 U1 K* |2 {# V/ A
<param-name>ContentType</param-name>, d' L0 X; {6 J
<param-value>text/html</param-value> I# [/ v- e' Z- k/ R
</init-param>( A6 a- J) N% J1 d [0 ?
<init-param>4 P: c, a# M1 s7 j9 V
<param-name>template_update_delay</param-name>6 O( U, {- z2 b* |7 z) m
<param-value>0</param-value>
3 T" \! Z! q' q( {! W</init-param>* b. {0 |4 d2 q. S5 @% @: c
<init-param>
: s" y* J1 K3 z. \9 z" l4 d( k<param-name>default_encoding</param-name>
4 ~! G# h1 b4 ~# G2 w6 I- i<param-value>GBK</param-value>
2 I% E/ I9 a2 f3 S4 | m5 I- r</init-param>
7 j5 _3 r( V, `) F9 |3 z! m/ V- t6 P<init-param>
. o' e m$ {; P& \<param-name>locale</param-name>
" C' t' X& I: Q; C; z; Y, S<param-value>zh_CN </param-value>. ], h# v& z) N6 r# v! B
</init-param>! H1 O( s6 M6 ?6 b. @
<init-param>) S" `! b, D* t }! H
<param-name>number_format</param-name>+ {' t9 E! n$ W; a7 U e( ^
<param-value>0.##########</param-value>
( C) @% ]! F9 e' A4 U) K$ e</init-param>
4 ]4 J% }- M: H" q% g<load-on-startup>2</load-on-startup>; J9 L) p2 T: L: K' ?) h
</servlet>) g, d& O$ Y4 p! O. L7 l2 i
<servlet-mapping>
4 {7 E7 y; G$ B" N<servlet-name>action</servlet-name>
" }1 l1 j0 O* L, ~+ C<url-pattern>*.do</url-pattern>
~1 _! i: |( u6 @, X1 t</servlet-mapping>
0 O4 D, U- H# z( `9 ~) E% Z7 `2 R0 n<servlet-mapping>! |! r; j* v, g# Q7 Y& c9 A* b
<servlet-name>freemarker</servlet-name>, r+ Y: w U/ }, ]/ l# Z% W3 r
<url-pattern>*.ftl</url-pattern>9 C+ M+ c- m' X5 w3 e/ _7 r
</servlet-mapping>
6 A, t$ m8 D: ]7 D B4 n% _ M& P
" [% |* n: }7 G" l! O5 H7 ]----------------------------------------------------------------------------8 \5 n# N& b, _0 d: @3 { T
三.常用语法. o/ V" p* r/ s6 B5 P8 g/ `8 e
EG.一个对象BOOK
' J2 |' h: ?% k6 j9 k
. C# f8 E" J* L' @1.输出 ${book.name}
% c" \1 W _9 {, X) }7 _空值判断:${book.name?if_exists },9 h; J1 Z3 u, H) N
${book.name?default(‘xxx’)}//默认值xxx
/ w5 s! d% c: ~$ G${ book.name!"xxx"}//默认值xxx. f' c: M( F j# h/ L+ V/ d! l& F! C( C
日期格式:${book.date?string('yyyy-MM-dd')}
8 ~7 w$ l3 ^) H# f数字格式:${book?string.number}--20
. X# C b$ t2 |: P" i${book?string.currency}--<#-- $20.00 -->
2 k g' n4 c* B3 K! D1 {${book?string.percent}—<#-- 20% -->
9 |& C5 @8 }8 S' ~, a插入布尔值:9 Y9 Q" Y1 a3 r' p% M: K7 h. r
<#assign foo=ture />4 c6 @8 r& a% q) t. _" m' E, N: N
${foo?string("yes","no")} <#-- yes -->
1 I U6 Z0 f* b! v3 F% c5 }! c. j3 z/ i
9 U/ I8 n+ s6 f4 m. T, S+ {" D2 j
6 g& f7 L" {+ ?/ \0 t
2.逻辑判断6 }1 w% {# c; J- ?. d
a:" s% d; [" C. o$ X
<#if condition>...3 k# \* C3 r) l7 e* t* b1 d
<#elseif condition2>...
7 d5 q# [- [) ^<#elseif condition3>......# e5 n! T7 o# \
<#else>...
: H$ Q0 V9 ^4 r5 y其中空值判断可以写成<#if book.name?? >
& E0 K5 a5 K0 S! @& C C7 {- {: Z5 t+ Q# ^2 G P( T1 `' W$ `5 S, B
</#if>
. K. ~( i2 _) ^4 K1 x5 i) P8 C/ K9 R4 Y3 {* ?9 E& Q9 @
b:, q% C# V8 W" a( N. {8 w
<#switch value>$ P, J" G: a7 h* F8 _+ K
<#case refValue1>! v% p& c' }# X$ H3 M' J$ \
...
6 x9 O5 `+ ^- d1 H$ M& @ J<#break>9 X* l2 Y- u+ l5 U
<#case refValue2>
/ I' \# Y6 t, B Z...
( _3 K3 ^1 }" E$ b# m# \' ]<#break>
0 u9 |' G, M; L# O7 w5 ?...
/ x; V1 i4 W; h- ~1 u6 g<#case refValueN>5 z) A% s' M3 b4 h3 }) B
.../ T8 g2 S! I* Y1 ]: U
<#break>! T# ~- ~! L) _& D2 g
<#default>
, v1 Y' }1 Q3 F) `' O/ d0 f5 E...
1 s) `4 ]1 V/ ]) {0 T- J</#switch>& e1 Y# f. s$ ^9 t
; q) ]) f8 _! s, O3.循环读取1 u5 @' X2 u& q* N. b, S: O( y
<#list sequence as item>
" u" l; e& a+ [9 B; x1 f* Z...
6 X6 A8 l& N- M' H3 A, b' \# t6 X</#list>2 L4 l- E. n4 Z9 F/ z$ H% H6 l' `
空值判断<#if bookList?size = 0></#list>
* i% `9 C" @, _
& [- {- W |6 Z# }/ De.g.& f( i' `) k% `' T! q, p
<#list employees as e>
6 D/ Q( z& a2 p7 F% n6 G${e_index}. ${e.name}) y9 `0 }0 T/ _7 J% R
</#list>
6 A w# h l, C4 V# J8 ?输出:' @0 U6 E( S I8 H5 y
1. Readonly
/ a0 Y7 K. r& v4 l1 G2. Robbin
% h( U* f% k* w, h4 P& {. a8 v: K6 b5 l9 B+ a
4.FreeMarker6 {1 H# X: y2 _+ d/ g5 ~, u, B
( Z5 o- t3 Q4 j2 y* s& @
3 宏/模板7 C8 K! A& X( a4 Q
宏Macro
x4 [7 q. M5 z6 `. ~( W4 r, w宏是在模板中使用macro指令定义
/ }( I$ D( V% e* A5 Xl.1 基本用法, l N" |& ]- q. B+ D- `
宏是和某个变量关联的模板片断,以便在模板中通过用户定义指令使用该变量,下面是一个例子:
( q9 d* v# |: k8 ]+ e7 P<#macro greet>
0 U- l! s( g- u# o% }, }) p<font size="+2">Hello Joe!</font>& V0 ^( c7 V: ^% y
</#macro>
) k4 C' \9 O' v调用宏时,与使用FreeMarker的其他指令类似,# v0 B" _5 E% \$ h# V3 D/ {
只是使用@替代FTL标记中的#。! D' P/ ~6 S, p0 ?
<@greet><[url=]/@greet[/url]>; L$ m& `/ \0 q9 Q
<#--<@greet/>-->& U! Q8 @" Z4 o. y. e
1 Z: T' p) s. C' j
在macro指令中可以在宏变量之后定义参数,如:; M. c/ M! R% W7 H4 ^
<#macro greet person>8 { l: t4 p3 C2 a& z
<font size="+2">Hello ${person}!</font>
, C. z" J5 y8 m: U</#macro>% i( E5 R, O! \; L# i) p
可以这样使用这个宏变量:6 l) t% W, a. Z: q! O
<@greet person="Fred"/>
: S' s/ c& J/ _3 R+ W& r但是下面的代码具有不同的意思:* g+ V9 K8 K, v0 H
<@greet person=Fred/>, ]& U8 i# A' G9 N" d6 W4 r; C
这意味着将Fred变量的值传给person参数,该值不仅是字符串,还可以是其它类型,甚至是复杂的表达式。5 p+ y3 i$ j' _4 d" j
2 H( L5 C, K" L宏可以有多参数,下面是一个例子:
. k8 j+ Z0 \; F3 U<#macro greet person color>, p: W7 M. z0 y+ l2 m8 V
<font size="+2" color="${color}">Hello ${person}!</font>
2 m; N. v9 E* F- a6 l</#macro>
/ h( F* t5 J- e1 J$ p可以这样使用该宏变量,其中参数的次序是无关的:, G; z5 P4 {5 z+ N
<@greet person="Fred" color="black"/>/ O8 p; M+ E8 `2 C, J
可以在定义参数时指定缺省值,否则,在调用宏的时候,必须对所有参数赋值:3 T; R) s A9 R
<#macro greet person color="black">4 s8 M) {- X# t0 N
<font size="+2" color="${color}">Hello ${person}!</font>" O* g* I5 e& S9 Z, ~. d p
</#macro>* t# ?) d, W; I, j
注意:宏的参数是局部变量,只能在宏定义中有效。
9 u* u) ?* N" m' c- l: v/ v# P5 i! a/ r0 g: p$ p
在宏里嵌套内容
% t3 V) r" Z. G; c" ]FreeMarker的宏可以有嵌套内容,
# h; R' n; ~* l1 f<#nested>指令会执行宏调用指令开始和结束标记之间的模板片断,举一个简单的例子:
, X$ a% E" W3 y1 i8 z) T/ r1 L<#macro border>
. Y; O0 B$ L( A( I! m<table border=4 cellspacing=0 cellpadding=4><tr><td>. \( Z, {6 J3 \& J
<#nested>& M J9 P8 [. E& a1 n4 d
</tr></td></table>6 Y. S8 b/ t/ Z1 D6 ?( P. K- X
</#macro>% P9 q1 t* @* N5 `$ O
执行宏调用:# E: i# h, K7 ~) u* R2 C2 T) P
<@border>The bordered text<[url=]/@border[/url]>
: @$ O! c' N! |; [% r7 V输出结果:* u* E7 t' Q* k4 N$ H' k. Y
<table border=4 cellspacing=0 cellpadding=4>' t4 Y! K5 G, x* L
<tr><td>9 W/ K l) v6 i/ B; x( }4 J4 N# _* `; l
The bordered text
. |8 |5 t3 y$ p8 O( H3 x</tr></td>
* h! @* |! @* _</table>
' g# g4 P" ` g! Q U" a<#nested>指令可以被多次调用,每次都会执行相同的内容。) y( J! `9 ^7 `6 \% i
<#macro do_thrice>% a0 C/ }* {+ P( z7 E" Q4 X
<#nested>
9 F9 Q% ^3 F/ g5 T<#nested>7 W# y B' D, g5 f% p f
<#nested>
2 i5 f! |1 L! Z) L' d3 d</#macro>3 r% W% t: t- e1 [
4 {" K, h; {6 S. x& C<@do_thrice> N4 l/ J# p6 t6 A9 ^) V" E9 k
Anything.( ]) s2 g3 J) |/ b/ x& Z) O$ J
<[url=]/@do_thrice[/url]>- [2 ^$ n* m# Z$ l9 w. O9 g
FMPP 输出结果:
' Y9 j3 u) o, B, i( o; [Anything.
" F: {8 p- \$ XAnything.
) o. y! Z1 l; \! k+ {Anything.
6 V+ @0 V* [! a& ?嵌套内容可以是有效的FTL,下面是一个有些复杂的例子,我们将上面三个宏组合起来:
- V# t7 [4 ?! F; o6 u! m<@border>* G- ^7 M$ Y1 r
<ul>; m% p$ X% }/ j- q/ q) a! L7 ?
<@do_thrice>) r# J* J u1 P% A. [( n2 j
<li><@greet person="Joe"/>: @- j/ I5 H) | w
<[url=]/@do_thrice[/url]>$ l, b1 H- g* E7 h \
</ul># i T0 _, ]3 ^ P5 I
<[url=]/@border[/url]>
; L. k! H; e i输出结果:
" D8 p+ E5 g2 _$ s& K! w% D6 l<table border=4 cellspacing=0 cellpadding=4><tr><td>1 G; f/ z' b4 \! y
<ul>7 d: [6 c4 j) r9 A4 p6 C; R6 d _0 G
<li><font size="+2">Hello Joe!</font>
' h0 _" h) F/ l) n; f<li><font size="+2">Hello Joe!</font>
# w+ H" `. J z, r<li><font size="+2">Hello Joe!</font>
9 b' _2 ]; a3 e! O$ G' ?4 @5 P5 T</ul>
% e1 S8 \# T) q' I) ^: u</tr></td></table>/ p; {; S! c% T& P3 G# j
宏定义中的局部变量对嵌套内容是不可见的,例如:
4 I8 R( _5 C* M$ _/ V- e3 \& R# ]<#macro repeat count>
4 [4 u; p1 M5 Z5 A0 k4 m<#local y = "test">% G, Q0 q9 x2 b' H7 J+ f/ i
<#list 1..count as x>; z( w( q6 a9 b" z
${y} ${count}/${x}: <#nested>
7 Z5 v; @4 _) Y! E* `( O</#list>
0 _9 i9 p7 w" `6 _; N. a</#macro>
) B* M. J A" l/ X8 a7 Q M<@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}<[url=]/@repeat[/url]>
+ Z9 n2 ]9 {& `2 } v1 B* e/ e输出结果:, Q# E6 {6 l2 u5 ?
test 3/1: ? ? ?4 }# U2 r% P3 C& l5 R2 q& I% Z
test 3/2: ? ? ?; B. ~& d _5 @7 d) @6 ^
test 3/3: ? ? ?
( d* T' B( {& o& @5 F5 _1 K. x7 ~( D) h
在宏定义中使用循环变量
8 ?' d) n0 q7 y: M/ Gnestted指令也可以有循环变量(循环变量的含义见下节),调用宏的时候在宏指令的参数后面依次列出循环变量的名字,格式如下:
7 c! f9 g) d0 T! s. c<@ macro_name paramter list; loop variable list[,]>' C/ G8 m3 L4 O4 ^# L0 c8 F$ j
例如:
% M* W; n% d$ Q' i) g- Y- L t<#macro repeat count>
1 R/ V+ D0 \6 X4 a2 d: f7 {( c<#list 1..count as x>
& J; @ V& E$ s1 Y- P# ~ X V<#nested x, x/2, x==count># I( g! ^3 [; v* T! R; J: K
</#list>- i7 x! Z$ l" M% i; V8 |0 }$ }% T5 y
</#macro>0 g v1 r i& I- t# q1 ]9 G1 T% o
<@repeat count=4 ; c, halfc, last>
/ {- }) P q$ {7 P; s${c}. ${halfc}<#if last> Last!</#if>
; B( b. J. `0 C- w; K+ @" y$ _<[url=]/@repeat[/url]>: S, |. Q/ {# k& }6 g
这里count是宏的参数,c, halfc,last则为循环变量,输出结果:5 c' [3 z' t2 A
1. 0.5, ~& E& ]" M1 }" ]2 J
2. 1" Q. K# y5 a% l7 O' q. W" i
3. 1.5
) h* \& j( }* L; D2 |. s1 P4. 2 Last!% O6 X1 k6 @/ A) ?
循环变量和宏标记指定的不同不会有问题,如果调用时少指定了循环变量,那么多余的值不可见。调用时多指定了循环变量,多余的循环变量
( V$ V% G3 O( } A6 N不会被创建:
% p! M- G. M5 B4 O# _. W h<@repeat count=4 ; c, halfc, last>4 @1 M- L" b3 t
${c}. ${halfc}<#if last> Last!</#if>
\$ R0 m6 G# ?4 S4 V# Z8 L<[url=]/@repeat[/url]>% Q2 O9 n! J6 ^3 R
<@repeat count=4 ; c, halfc>9 u- ~8 G. }+ b* i
${c}. ${halfc}* |# k+ w5 O/ t1 v( O7 q
<[url=]/@repeat[/url]>! Q+ f" m& Y; u6 A2 v" l$ d8 ~
<@repeat count=4>
" b6 _) B" q6 K) d! j& f6 sJust repeat it...; t/ T. s& B. j6 {' M A
<[url=]/@repeat[/url]>
5 A- m/ s% t: F. v. e5 n& j7 {在模板中定义变量5 }* p: @5 {% Z) j2 t( h
在模板中定义的变量有三种类型:
9 D: [. X4 h$ f) }+ ]/ c8 e0 `; aplain变量:可以在模板的任何地方访问,包括使用include指令插入的模板,使用assign指令创建和替换。
4 `; g$ l/ a: P, I2 W局部变量:在宏定义体中有效,使用local指令创建和替换。$ w! U1 X& [4 O/ H8 U
循环变量:只能存在于指令的嵌套内容,由指令(如list)自动创建;宏的参数是局部变量,而不是循环变量
8 b% `' ^; p9 S" h6 F局部变量隐藏(而不是覆盖)同名的plain变量;循环变量隐藏同名的局部变量和plain变量,下面是一个例子:8 l; H% Y# r' R# @! t$ l4 }
<#assign x = "plain">
4 i' v$ x% |9 }5 s6 u, f+ u3 e6 }, x* r
${x} <#-- we see the plain var. here -->3 `$ j) W) J- a8 P
<@test/>3 x/ W% a, d+ J. H
6. ${x} <#-- the value of plain var. was not changed -->
5 l4 Q% `5 W5 E/ c9 G<#list ["loop"] as x>" A4 N7 K. C8 z9 s
7. ${x} <#-- now the loop var. hides the plain var. -->
. s/ H0 R$ v8 n- z! a& }" U- k<#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
& f: f. k0 h! {: N/ U. S$ I8. ${x} <#-- it still hides the plain var. --> P5 m4 N# [" N7 e
</#list>
6 F* G" i* w$ S9 m" E% Z9. ${x} <#-- the new value of plain var. -->4 D. o6 K) _0 M! ]( W8 p
<#macro test>
0 s7 S5 n x, n, p) E7 n2. ${x} <#-- we still see the plain var. here -->4 W8 z% A1 i# q* z
<#local x = "local">
2 q, F+ s- r' @9 [1 v8 R" [% {2 S3. ${x} <#-- now the local var. hides it -->
# `+ j0 c6 S M& N# |$ w( ?/ A<#list ["loop"] as x>
3 \: S# K* n( q. @0 Y4. ${x} <#-- now the loop var. hides the local var. -->
2 A1 [1 r( F N" l: v" V</#list>
3 v3 s& F# J' f5. ${x} <#-- now we see the local var. again -->
5 {* {" }$ S) e/ B+ I0 M$ u+ ]- P</#macro>0 Q; o) j) w) c: `
输出结果:- V0 D& t2 V" S% n6 }2 {
1. plain
# N: f8 ^1 [5 w. Y/ ?: G: x2. plain; J, A8 z0 D% R: k/ M# s6 i# z. y
3. local/ Y) I" Y8 o# |# E7 f3 U3 q
4. loop" o4 G; f" A" }- I! Y
5. local I9 j3 r8 O4 ], W
6. plain) U0 f/ w0 k( H, X( l
7. loop
8 f$ R* u( w7 t* O3 m) Y8. loop
# p: f# B7 c; H, u/ S9. plain2. A0 R( }0 S. l/ U; ~8 o! O# T
内部循环变量隐藏同名的外部循环变量,如:6 e& I ]/ w' E* q# S
<#list ["loop 1"] as x>& n2 h' R) p% H. r
${x}) s3 e0 O7 b4 I# y1 g. H$ Y0 ]
<#list ["loop 2"] as x>+ L' A- ^5 O9 i/ |( H: W8 n& R
${x}
, b& I( V) v& J8 o9 s<#list ["loop 3"] as x>
* T; O' n2 i% g W. W${x}- C$ L9 w! J0 C7 b `
</#list>
5 M& A& L4 N- z) T, d${x}
' L( G+ t$ a, h$ y5 d</#list>1 _0 `1 U* M7 U7 s( K% \
${x}/ L( a3 g' d( P: J- m @- n, N
</#list>
4 v9 C1 u& t5 O. [' M( D输出结果:1 |" n9 }, ?2 q, Z
loop 1
9 o) W& K' U' T1 {( {loop 2( b4 n- ^6 J2 K! w, Q( x
loop 3
4 w# c# M2 B& n' j3 wloop 2
$ Z8 X& Y- h ?7 K' Kloop 18 P/ P3 ?- k/ O1 A0 N) J3 m/ `
模板中的变量会隐藏(而不是覆盖)数据模型中同名变量,如果需要访问数据模型中的同名变量,使用特殊变量global,下面的例子假设数据) b! m: U$ u( v* F
模型中的user的值是Big Joe:
' @) y ^* t9 h" _<#assign user = "Joe Hider">
4 V! N' f1 V2 T4 O. r${user} <#-- prints: Joe Hider -->
+ {9 _2 X) J& A; N2 O${.globals.user} <#-- prints: Big Joe -->
7 i8 J. s& @3 U- X u6 b名字空间! [/ J7 [; B% i8 j
通常情况,只使用一个名字空间,称为主名字空间,但为了创建可重用的宏、变换器或其它变量的集合(通常称库),必须使用多名字空间,
) S N5 X. r2 Q# {- E其目的是防止同名冲突
7 ~! v" A! l/ O2 U创建库
6 Y: o" a" V, l0 w/ I下面是一个创建库的例子(假设保存在lib/my_test.ftl中):
' U1 W* U( j7 `; P<#macro copyright date>4 ^5 r6 h) S& [% p9 |$ i
<p>Copyright (C) ${date} Julia Smith. All rights reserved./ Y% t- O/ a7 _- p' Z
<br>Email: ${mail}</p>6 L$ r V( q8 U* m+ ~- r3 ^& s2 p, ]
</#macro>
' V* ?7 K2 Q) d# y* d. H<#assign mail = "jsmith@acme.com">( I5 a; i1 z# t
使用import指令导入库到模板中,Freemarker会为导入的库创建新的名字空间,并可以通过import指令中指定的散列变量访问库中的变量:9 T, c& J3 f, l+ W: Z/ ?( U
<#import "/lib/my_test.ftl" as my>- _" w d) r* ^2 F1 {) A& n5 R" \
<#assign mail="fred@acme.com">
( ]* s: b$ g# {9 j, t9 Q$ u) S<@my.copyright date="1999-2002"/>! u- {% J2 |8 w2 ~& L1 x8 R Y& Q8 ]
${my.mail}' _! ~# G5 |) E5 T% G1 { Q
${mail}
% j+ t3 @; O# b, M5 k输出结果:
s; j) _* ]0 n4 T) Q; S( h<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
: h* S2 \3 Z% t+ V0 n- u<br>Email: jsmith@acme.com</p>$ |; O2 g1 s. U
jsmith@acme.com& [- |3 z1 c# {8 e0 u4 ^0 R# D; u
fred@acme.com
7 [3 k, K, _0 O! A. E1 g可以看到例子中使用的两个同名变量并没有冲突,因为它们位于不同的名字空间。还可以使用assign指令在导入的名字空间中创建或替代变量4 I5 y8 m' m' l
,下面是一个例子:
# @9 R `: q5 r<#import "/lib/my_test.ftl" as my>
/ _, r, a* \0 a: W${my.mail}- n6 i* C% L# _: p4 A
<#assign mail="jsmith@other.com" in my>
6 L, b: n3 }$ o5 S' e$ q${my.mail}
1 A `6 O2 j, a* W- d, J输出结果:
3 M, |5 Y) ~) m. M \2 G, O8 Vjsmith@acme.com; `. x% ^4 |& u7 |: [2 ~( ]. J& u
jsmith@other.com
. k0 ?; d' M* p- g数据模型中的变量任何地方都可见,也包括不同的名字空间,下面是修改的库:
( T0 t0 K5 q! n9 G) A q) }% Z3 C<#macro copyright date>% U( J/ O$ @# g) D& f
<p>Copyright (C) ${date} ${user}. All rights reserved.</p>! J2 U2 q/ u; k
</#macro>2 q& V% K$ v/ ^' `- `" E
<#assign mail = "[url=mailto:%24%7Buser%7D@acme.com]${user}@acme.com[/url]">7 z) l& W' X! T3 a2 L0 o2 W% W' ?
假设数据模型中的user变量的值是Fred,则下面的代码:1 q% P' L$ d4 F, q# d
<#import "/lib/my_test.ftl" as my>* {6 f& j" Y" D9 B0 X6 k
<@my.copyright date="1999-2002"/>
+ Y) L- m' f0 {: O8 Q: [' c' m$ Q${my.mail}
& E' s# ?3 p3 D4 b输出结果:
1 n T3 Y z* n0 s+ G<p>Copyright (C) 1999-2002 Fred. All rights reserved.</p>Fred@acme.com
5 z# _, O1 s" p
5 |6 V" |& F( c& E0 N& N8 H' l% |四.Freemarker与Struts结合
; \, U1 Q2 B- z9 Z; Q( L1.输出文件换成以ftl格式的文件
$ c% x# O, l1 E) OE.G.
9 P3 O( w8 y/ P<action name="bookActionForm" parameter="method" path="/bookAction" scope="request" type="example.BookAction"3 s& B, \: l/ J! [1 z% y9 I; X
validate="true">
# U* B# ^1 P/ ^! i2 t<forward name="list" path="/index.ftl"/>
& {7 |; h2 \4 s' L: j</action>- J/ A7 N6 S# b2 T) h3 s! c
2.使用struts,jstl等标签" V0 V6 c5 _# ]! U) |
a.导入à<#global html=JspTaglibs["/WEB-INF/tags/struts-html.tld"]>
9 W# V6 z4 P! ~9 H3 b! [( ~或<#assign html=JspTaglibs["/WEB-INF/struts-html.tld"]>
+ d( o' K# f7 X9 K0 v# |- ?6 D7 c<#assign bean=JspTaglibs["/WEB-INF/struts-bean.tld"]>
" |) i4 c- V! A2 e6 b# b/ ?5 o<#assign logic=JspTaglibs["/WEB-INF/struts-logic.tld"]>" o5 x) V0 N2 g) Z; f" y
b.使用à<@bean.page id="request" property="request"/>,
" O- Z3 T. c j! b$ U p: Q<@html.text property="vo.newsTitle" styleClass="input1"/>
8 s2 T, F: w; G5 M/ v ^: ^五.用Freemarker生成Html页面
) k2 M5 M* ]# f, U* z& U& V' W例子:MakeFileManager.java
5 S7 r" m- M- z) C) `, l! p* J2 ^( ]" r& V/ D' X4 N6 z
package example;% q$ f4 W8 f/ v5 b7 x( ^2 T1 g! I
import freemarker.template.Configuration;
/ T2 V) u7 X0 U7 c1 u6 n; ]7 iimport java.text.SimpleDateFormat;& @$ R% n! |, H' ^7 R
import java.io.File;$ ?3 b& p% G/ d+ J2 K
import freemarker.template.DefaultObjectWrapper;7 [5 i# o) r/ b) D
import java.util.Map;
5 T' I# q0 i# w+ ^% Kimport java.util.HashMap;
% l" T2 H+ ^% m s7 Iimport java.io.Writer;
7 B8 B: E2 l4 i+ O/ e: c. b/ b* rimport java.io.OutputStreamWriter;$ r7 L7 v( h+ D& @
import java.io.FileOutputStream;1 }$ G+ B" T0 Q. ?* q
import freemarker.template.TemplateException;
. V6 B' o. n, c$ e2 [: O% U/ Aimport java.io.IOException;# I y* g2 r4 L; p& e
import freemarker.template.Template;% e% g. F4 D$ V6 o
public class MakeFileManager {, I( R# G* f: [& P6 a' J1 p# y# @
public String make(Book book, BookFtl bookFtl) {; ~& ^/ g5 H4 n- Y( C
Configuration cfg = new Configuration();//配制
7 _7 h. Y: D4 H: ]9 U1 L# k. E3 hString realPath = bookFtl.getRealPath();9 ?, d4 ~ I/ N, t
String templatePath = realPath + "/WEB-INF/templates/book";$ j* P! B6 N( e: l# P1 }
String cDateStr = "book/" +7 B4 k/ L% @# W3 w
new SimpleDateFormat("yyyyMMdd").format(new java.util.
+ P' O; F/ O; m# a/ L" GDate());
+ p9 i; [+ Z2 }. T" B, `) a8 ^9 eString filePostfix = ".html";3 \* M2 |2 Q0 {( L- y2 G3 ]2 [* @
String path = realPath + "/" + cDateStr;
& Z0 J$ u( j+ V! IString fileTimeName = new SimpleDateFormat("yyyyMMddhhmmss").format(new
7 K$ Q) k' C; i! ?* j0 Q* _/ sjava.util.Date());3 x. o( l% l" Q% R& ~% m; N8 R; I6 F
String returnFileName = cDateStr + "/" + fileTimeName + filePostfix;6 a- q G9 J" o4 Z9 q
String fileName = "";
( j4 G6 f% r3 GFile bookDir = new File(path);% {/ ]5 ]6 J) }- k6 g
if (bookDir.exists()) {2 ^" a# D& {+ z: q
fileName = path + "/" + fileTimeName + filePostfix;
; h& U( @. w5 E} else {, h6 @1 e- `7 D; O0 m
bookDir.mkdirs();) }( J/ F( X, T% W% ~) V) D
fileName = path + "/" + fileTimeName + filePostfix;' y. U2 k1 X/ a
}
6 s w* P1 o" H" ?/ ?- D6 L# h+ t: ktry {( u k6 q. c+ W- n$ z0 J/ `
//设置freemarker的参数# x& @/ w" M+ U- l0 D; k5 N
cfg.setNumberFormat("0.##########");//生成html文件时web.xml配制无效* Y% w$ K. g9 @/ v
//cfg.setEncoding();
4 f( |+ b7 Q8 y$ |0 R" w2 h* ?cfg.setDirectoryForTemplateLoading(new File(templatePath));9 F8 c+ n9 O, d Q8 U6 T$ k. A
cfg.setObjectWrapper(new DefaultObjectWrapper());
9 Z6 d$ Q' Z% I4 MTemplate bookTemplate = cfg.getTemplate(bookFtl.getTemplateName());//模板对象* ~7 s4 G) g& t/ Y: g* r( \
Map root = new HashMap();
/ y( [+ v0 h W- f( Croot.put("book", book);; ~: P" w( p* V( {3 U) A2 Z
root.put("book2",book);0 I% o+ X5 l- w8 c- U1 {5 D/ u1 {
Writer out = new OutputStreamWriter(new FileOutputStream(fileName));5 k' [# \ T# ]% E( F; E! z
try {
' W2 n1 t& U& ~, ]; rbookTemplate.process(root, out);- q+ r* S! b* g/ p! t3 }( M
} catch (TemplateException e) {! e+ x; s4 \& x3 L$ F
e.printStackTrace();- y7 d) K* h/ r) C, {
}' W; G- u3 }6 E& g% W
out.flush();2 r) C& S1 U r, H
} catch (IOException e) {1 f s+ A3 U6 [6 S$ _
e.printStackTrace();
, {0 Z5 U' h G6 H3 U% U}
0 t2 [- T6 I& Creturn returnFileName;. \% k/ O; u% H S/ p+ f( F m- M8 w
}
: a3 o& T8 ]! P! @8 Q}; j( t0 n h4 F+ o( {- _
1 m/ l3 K4 s7 w4 |2 s
|
|