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