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