我的日常

登录/注册
您现在的位置:论坛 盖世程序员(我猜到了开头 却没有猜到结局) 盖世程序员 > FreeMark环境搭建与配置如何生成Html页面
总共48086条微博

动态微博

查看: 1932|回复: 0

FreeMark环境搭建与配置如何生成Html页面

[复制链接]

326

主题

72

听众

999

金钱

实习版主

该用户从未签到

优秀版主

跳转到指定楼层
楼主
发表于 2014-09-18 10:12:48 |只看该作者 |倒序浏览
一.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

科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
7、科帮网管理员和版主有权不事先通知发贴者而删除本文


JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

快速回复
您需要登录后才可以回帖 登录 | 立即注册

   

关闭

站长推荐上一条 /1 下一条

发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
快速回复 返回顶部 返回列表