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