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