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