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