﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Java民工的铁皮房-文章分类-Struts2</title><link>http://www.blogjava.net/wjywilliam/category/35145.html</link><description>Consciousness Of Programming - wjywilliam
想飞，总是会飞的......
</description><language>zh-cn</language><lastBuildDate>Thu, 09 Jun 2011 18:16:49 GMT</lastBuildDate><pubDate>Thu, 09 Jun 2011 18:16:49 GMT</pubDate><ttl>60</ttl><item><title>FreeMarker特性介绍与概述</title><link>http://www.blogjava.net/wjywilliam/articles/351928.html</link><dc:creator>wjywilliam</dc:creator><author>wjywilliam</author><pubDate>Wed, 08 Jun 2011 09:46:00 GMT</pubDate><guid>http://www.blogjava.net/wjywilliam/articles/351928.html</guid><wfw:comment>http://www.blogjava.net/wjywilliam/comments/351928.html</wfw:comment><comments>http://www.blogjava.net/wjywilliam/articles/351928.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wjywilliam/comments/commentRss/351928.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wjywilliam/services/trackbacks/351928.html</trackback:ping><description><![CDATA[
		<p>
				<strong>一．Freemarker简介<br /><br />二．环境搭建与配置</strong>
		</p>
		<p>
				<strong>三．常用语法</strong>
		</p>
		<p>
				<strong>四．与Struts结合</strong>
		</p>
		<p>
				<strong>五．生成Html页面</strong>
		</p>
		<p>
				<br />
				<strong>
						<font size="5">一．Freemarker简介<br /></font>
				</strong>什么是Freemarker:.</p>
		<p>Freemaker是一个”模板引擎”,也可以说是一个基于模板技术的生成文本输出的一个通用工具.它是一个JAVA的包,一个JAVA程序员可以使用的</p>
		<p>类库.本身并不是一个对最终用户的应用程序.但是,程序员可以把它应用到他们的产品中.</p>
		<p>FreeMarker是设计为可以生成WEB PAGES.它是基于SERVLET遵循MVC模式的.这个思路是应用MVC模式要降低分离,网页设计人员和程序员的耦合.</p>
		<p>每个人都可以做他们擅长的工作.网页设计人员可以改变网页的面貌,而并不需要程序员的重新编译.因为业务逻辑和页面的设计已经被分离开了</p>
		<p>.模板是不能由复杂的程序片断组成的.即便网页设计人员和程序员是一个人. 分离是有必要的.它能使程序更加的灵活和清晰.</p>
		<p>虽然Freemarker能编程,但是它并不是一个编程语言.它是为程序显示数据而准备的.(像数据库SQL语句的查询.)以及.Freemarker仅仅是利用模</p>
		<p>板加上数据生成文本页面.</p>
		<p>Freemarker并不是一个WEB应用程序框架.可以说是一个WEB应用框架的一个组件.但是FREEMARKER引擎本身并不了解HTTP或者SERVLETS.它只不过</p>
		<p>生成文本而已.注意,它是MVC框架的一个组件(如STRUTS),也可以在模板中使用JSP标签.</p>
		<p>  Freemarker下载地址为：<a href="http://www.freemarker.org/index.html">http://www.freemarker.org/index.html</a></p>
		<p>一般的用途:</p>
		<p>l 能用来生成任意格式的文本:HTML,XML,RTF,JAVA源码,等等.</p>
		<p>l可以更好的嵌入到你的产品中,轻量级的.并不需要servlet环境.不依赖javax.servlet.classes.</p>
		<p>l可插入的模板读取器:你可以从任意的源码读取任意的模板.本地的文件,数据库等等.</p>
		<p>l你可以做任意你想生成的文本.存储为本地文件.可以用来发送EMAIL或返回到WEB浏览器中.</p>
		<p> </p>
		<p>强大的模板语言</p>
		<p>l完整的指令:include,if/elseif/else,loop.</p>
		<p>l 建立和修改模板中的变量.</p>
		<p>l 能用复杂的表达式在任意地方指定变量.</p>
		<p>n字符串操作:concateration,sub-string,uppercase,capitalize,escaping.等等</p>
		<p>n十进制数学计算.</p>
		<p>n BOOL</p>
		<p>n读取数组和相关的数组元素.</p>
		<p>n可以自己添加特殊的计算方法.</p>
		<p>l宏指令</p>
		<p>l 命名空间用来创建和维护宏指令库或者把大的项目分成许多模块.并不用担心命名冲突<br /></p>
		<p>
		</p>
		<p>
				<font size="5">
						<font size="3">----------------------------------------------------------------------------</font>
						<br />
						<strong>二．环境搭建与配置<br /></strong>
				</font>&lt;!—freemarker初始配置--&gt;<br /> <br />&lt;servlet&gt;<br />&lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;freemarker.ext.servlet.FreemarkerServlet&lt;/servlet-class&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;TemplatePath&lt;/param-name&gt;<br />&lt;param-value&gt;/&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;NoCache&lt;/param-name&gt;<br />&lt;param-value&gt;true&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;ContentType&lt;/param-name&gt;<br />&lt;param-value&gt;text/html&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;template_update_delay&lt;/param-name&gt;<br />&lt;param-value&gt;0&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;default_encoding&lt;/param-name&gt;<br />&lt;param-value&gt;GBK&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;locale&lt;/param-name&gt;<br />&lt;param-value&gt;zh_CN &lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;number_format&lt;/param-name&gt;<br />&lt;param-value&gt;0.##########&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;load-on-startup&gt;2&lt;/load-on-startup&gt;<br />&lt;/servlet&gt;<br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt;action&lt;/servlet-name&gt;<br />&lt;url-pattern&gt;*.do&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;<br />&lt;url-pattern&gt;*.ftl&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br /> <br />----------------------------------------------------------------------------<br /><strong><font size="5">三．常用语法<br /></font></strong> EG.一个对象BOOK</p>
		<p>
				<br />  <strong>1.输出 ${book.name}</strong></p>
		<p>空值判断：${book.name?if_exists },</p>
		<p>${book.name?default(‘xxx’)}//默认值xxx<br />${ book.name!"xxx"}//默认值xxx</p>
		<p>日期格式：${book.date?string('yyyy-MM-dd')}</p>
		<p>数字格式：${book?string.number}--20<br />${book?string.currency}--&lt;#-- $20.00 --&gt;<br />${book?string.percent}—&lt;#-- 20% --&gt;</p>
		<p>插入布尔值：<br />&lt;#assign foo=ture /&gt;<br />${foo?string("yes","no")} &lt;#-- yes --&gt;<br /> <br /> <br /> <br /> <br /><strong>2．逻辑判断<br /></strong>a:<br />&lt;#if condition&gt;...<br />&lt;#elseif condition2&gt;...<br />&lt;#elseif condition3&gt;......<br />&lt;#else&gt;...<br />其中空值判断可以写成&lt;#if book.name?? &gt;<br /> <br />&lt;/#if&gt;</p>
		<p>
				<br />b:<br />&lt;#switch value&gt;<br />  &lt;#case refValue1&gt;<br />    ...<br />    &lt;#break&gt;<br />  &lt;#case refValue2&gt;<br />    ...<br />    &lt;#break&gt;<br />  ...<br />  &lt;#case refValueN&gt;<br />    ...<br />    &lt;#break&gt;<br />  &lt;#default&gt;<br />    ...<br />&lt;/#switch&gt;<br /> <br /><strong>3．循环读取<br /></strong>&lt;#list sequence as item&gt;<br />...<br />&lt;/#list&gt;<br />空值判断&lt;#if bookList?size = 0&gt;&lt;/#list&gt;</p>
		<p>
				<br />e.g.<br />&lt;#list employees as e&gt;<br />${e_index}. ${e.name}<br />&lt;/#list&gt;<br />输出:<br />1. Readonly<br />2. Robbin</p>
		<p>
				<br />4.FreeMarker </p>
		<p>
				<br />
				<strong>4 宏/模板</strong>
		</p>
		<p>宏Macro</p>
		<p>宏是在模板中使用macro指令定义<br />l.1 基本用法<br />宏是和某个变量关联的模板片断，以便在模板中通过用户定义指令使用该变量，下面是一个例子：</p>
		<p>&lt;#macro greet&gt;<br />  &lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;<br />&lt;/#macro&gt;</p>
		<p>
				<strong>调用宏时，与使用FreeMarker的其他指令类似，<br /> 只是使用@替代FTL标记中的#。</strong>
		</p>
		<p>&lt;@greet&gt;&lt;<a>/@greet</a>&gt; </p>
		<p>&lt;#--&lt;@greet/&gt;--&gt;</p>
		<p>
				<br />
				<strong>在macro指令中可以在宏变量之后定义参数</strong>，如：</p>
		<p>&lt;#macro greet person&gt;<br />  &lt;font size="+2"&gt;Hello ${person}!&lt;/font&gt;<br />&lt;/#macro&gt;<br /> 可以这样使用这个宏变量：<br />  &lt;@greet person="Fred"/&gt;<br /> 但是下面的代码具有不同的意思：<br />  &lt;@greet person=Fred/&gt;<br /> 这意味着将Fred变量的值传给person参数，该值不仅是字符串，还可以是其它类型，甚至是复杂的表达式。</p>
		<p>
				<br />
				<strong>宏可以有多参数，下面是一个例子</strong>：<br />&lt;#macro greet person color&gt;<br />  &lt;font size="+2" color="${color}"&gt;Hello ${person}!&lt;/font&gt;<br />&lt;/#macro&gt;</p>
		<p>可以这样使用该宏变量，其中参数的次序是无关的：<br />&lt;@greet person="Fred" color="black"/&gt;</p>
		<p>可以在定义参数时指定缺省值，否则，在调用宏的时候，必须对所有参数赋值：<br />&lt;#macro greet person color="black"&gt;<br />  &lt;font size="+2" color="${color}"&gt;Hello ${person}!&lt;/font&gt;<br />&lt;/#macro&gt;</p>
		<p>注意：宏的参数是局部变量，只能在宏定义中有效。</p>
		<p>
		</p>
		<p>
				<br />在宏里嵌套内容<br /><strong>FreeMarker的宏可以有嵌套内容，<br /></strong>&lt;#nested&gt;指令会执行宏调用指令开始和结束标记之间的模板片断，举一个简单的例子：</p>
		<p>&lt;#macro border&gt;<br />  &lt;table border=4 cellspacing=0 cellpadding=4&gt;&lt;tr&gt;&lt;td&gt;<br />    &lt;#nested&gt;<br />  &lt;/tr&gt;&lt;/td&gt;&lt;/table&gt;<br />&lt;/#macro&gt;</p>
		<p>执行宏调用：<br />&lt;@border&gt;The bordered text&lt;<a>/@border</a>&gt;<br />输出结果：<br />&lt;table border=4 cellspacing=0 cellpadding=4&gt;<br /> &lt;tr&gt;&lt;td&gt;<br />      The bordered text<br />   &lt;/tr&gt;&lt;/td&gt;<br />&lt;/table&gt;</p>
		<p>&lt;#nested&gt;指令可以被多次调用，每次都会执行相同的内容。<br />&lt;#macro do_thrice&gt;<br />  &lt;#nested&gt;<br />  &lt;#nested&gt;<br />  &lt;#nested&gt;<br />&lt;/#macro&gt;</p>
		<p>
				<br />&lt;@do_thrice&gt;<br />  Anything.<br />&lt;<a>/@do_thrice</a>&gt;</p>
		<p>FMPP 输出结果：<br />Anything.<br />Anything.<br />Anything.</p>
		<p>嵌套内容可以是有效的FTL，下面是一个有些复杂的例子，我们将上面三个宏组合起来：<br />&lt;@border&gt;<br />  &lt;ul&gt;<br />  &lt;@do_thrice&gt;<br />    &lt;li&gt;&lt;@greet person="Joe"/&gt;<br />  &lt;<a>/@do_thrice</a>&gt;<br />  &lt;/ul&gt;<br />&lt;<a>/@border</a>&gt;<br />输出结果：<br />&lt;table border=4 cellspacing=0 cellpadding=4&gt;&lt;tr&gt;&lt;td&gt;<br />  &lt;ul&gt;<br />    &lt;li&gt;&lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;<br />    &lt;li&gt;&lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;<br />    &lt;li&gt;&lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;<br />  &lt;/ul&gt;<br />  &lt;/tr&gt;&lt;/td&gt;&lt;/table&gt;</p>
		<p>
				<strong>宏定义中的局部变量对嵌套内容是不可见的</strong>，例如：<br />&lt;#macro repeat count&gt;<br />  &lt;#local y = "test"&gt;<br />  &lt;#list 1..count as x&gt;<br />    ${y} ${count}/${x}: &lt;#nested&gt;<br />  &lt;/#list&gt;<br />&lt;/#macro&gt;</p>
		<p>&lt;@repeat count=3&gt;${y?default("?")} ${x?default("?")} ${count?default("?")}&lt;<a>/@repeat</a>&gt;</p>
		<p>输出结果：<br />test 3/1: ? ? ?<br />test 3/2: ? ? ?<br />test 3/3: ? ? ?</p>
		<p>
				<br />
				<strong>在宏定义中使用循环变量<br /></strong>nestted指令也可以有循环变量（循环变量的含义见下节），调用宏的时候在宏指令的参数后面依次列出循环变量的名字，格式如下：</p>
		<p>&lt;@ macro_name paramter list; loop variable list[,]&gt;</p>
		<p>例如：<br />&lt;#macro repeat count&gt;<br />  &lt;#list 1..count as x&gt;<br />    &lt;#nested x, x/2, x==count&gt;<br />  &lt;/#list&gt;<br />&lt;/#macro&gt;</p>
		<p>&lt;@repeat count=4 ; c, halfc, last&gt;<br />  ${c}. ${halfc}&lt;#if last&gt; Last!&lt;/#if&gt;<br />&lt;<a>/@repeat</a>&gt;</p>
		<p>这里count是宏的参数，c, halfc,last则为循环变量，输出结果：<br />  1. 0.5<br />  2. 1<br />  3. 1.5<br />  4. 2 Last!<br />循环变量和宏标记指定的不同不会有问题，如果调用时少指定了循环变量，那么多余的值不可见。调用时多指定了循环变量，多余的循环变量</p>
		<p>不会被创建：<br />&lt;@repeat count=4 ; c, halfc, last&gt;<br />  ${c}. ${halfc}&lt;#if last&gt; Last!&lt;/#if&gt;<br />&lt;<a>/@repeat</a>&gt;</p>
		<p>&lt;@repeat count=4 ; c, halfc&gt;<br />  ${c}. ${halfc}<br />&lt;<a>/@repeat</a>&gt;</p>
		<p>&lt;@repeat count=4&gt;<br />  Just repeat it...<br />&lt;<a>/@repeat</a>&gt;</p>
		<p>
				<strong>在模板中定义变量<br /></strong>在模板中定义的变量有三种类型：<br />plain变量：可以在模板的任何地方访问，包括使用include指令插入的模板，使用assign指令创建和替换。<br />局部变量：在宏定义体中有效，使用local指令创建和替换。<br />循环变量：只能存在于指令的嵌套内容，由指令（如list）自动创建；宏的参数是局部变量，而不是循环变量<br />局部变量隐藏（而不是覆盖）同名的plain变量；循环变量隐藏同名的局部变量和plain变量，下面是一个例子：</p>
		<p>&lt;#assign x = "plain"&gt;<br /> <br />${x}  &lt;#-- we see the plain var. here --&gt;</p>
		<p>&lt;@test/&gt;<br />  6. ${x}  &lt;#-- the value of plain var. was not changed --&gt;<br />  &lt;#list ["loop"] as x&gt;<br />  7. ${x}  &lt;#-- now the loop var. hides the plain var. --&gt;<br />    &lt;#assign x = "plain2"&gt; &lt;#-- replace the plain var, hiding does not mater here --&gt;<br />  8. ${x}  &lt;#-- it still hides the plain var. --&gt;<br />  &lt;/#list&gt;<br />  9. ${x}  &lt;#-- the new value of plain var. --&gt;<br />  &lt;#macro test&gt;<br />  2. ${x}  &lt;#-- we still see the plain var. here --&gt;<br />  &lt;#local x = "local"&gt;<br />  3. ${x}  &lt;#-- now the local var. hides it --&gt;<br />  &lt;#list ["loop"] as x&gt;<br />    4. ${x}  &lt;#-- now the loop var. hides the local var. --&gt;<br />  &lt;/#list&gt;<br />  5. ${x}  &lt;#-- now we see the local var. again --&gt;<br />&lt;/#macro&gt;<br />输出结果：<br />  1. plain<br />  2. plain<br />  3. local<br />  4. loop<br />  5. local<br />  6. plain<br />  7. loop<br />  8. loop<br />  9. plain2<br />内部循环变量隐藏同名的外部循环变量，如：<br />&lt;#list ["loop 1"] as x&gt;<br />  ${x}<br />  &lt;#list ["loop 2"] as x&gt;<br />    ${x}<br />    &lt;#list ["loop 3"] as x&gt;<br />      ${x}<br />    &lt;/#list&gt;<br />    ${x}<br />  &lt;/#list&gt;<br />  ${x}<br />&lt;/#list&gt;<br />输出结果：<br />loop 1<br />    loop 2<br />      loop 3<br />    loop 2<br />  loop 1<br />模板中的变量会隐藏（而不是覆盖）数据模型中同名变量，如果需要访问数据模型中的同名变量，使用特殊变量global，下面的例子假设数据</p>
		<p>模型中的user的值是Big Joe：<br />&lt;#assign user = "Joe Hider"&gt;<br />${user}          &lt;#-- prints: Joe Hider --&gt;<br />${.globals.user} &lt;#-- prints: Big Joe --&gt;<br />名字空间<br />通常情况，只使用一个名字空间，称为主名字空间，但为了创建可重用的宏、变换器或其它变量的集合（通常称库），必须使用多名字空间，</p>
		<p>其目的是防止同名冲突<br />创建库<br />下面是一个创建库的例子（假设保存在lib/my_test.ftl中）：<br />&lt;#macro copyright date&gt;<br />  &lt;p&gt;Copyright (C) ${date} Julia Smith. All rights reserved.<br />  &lt;br&gt;Email: ${mail}&lt;/p&gt;<br />&lt;/#macro&gt; <br />&lt;#assign mail = "<a href="mailto:jsmith@acme.com">jsmith@acme.com</a>"&gt;<br />使用import指令导入库到模板中，Freemarker会为导入的库创建新的名字空间，并可以通过import指令中指定的散列变量访问库中的变量：<br />&lt;#import "/lib/my_test.ftl" as my&gt;<br />&lt;#assign mail="<a href="mailto:fred@acme.com">fred@acme.com</a>"&gt;<br />&lt;@my.copyright date="1999-2002"/&gt;<br />${my.mail}<br />${mail}<br />输出结果：<br />&lt;p&gt;Copyright (C) 1999-2002 Julia Smith. All rights reserved.<br />  &lt;br&gt;Email: <a href="mailto:jsmith@acme.com%3C/p">mailto:jsmith@acme.com%3C/p</a>&gt;<br /><a href="mailto:jsmith@acme.com">jsmith@acme.com</a><br /><a href="mailto:fred@acme.com">fred@acme.com</a><br />可以看到例子中使用的两个同名变量并没有冲突，因为它们位于不同的名字空间。还可以使用assign指令在导入的名字空间中创建或替代变量</p>
		<p>，下面是一个例子：<br />&lt;#import "/lib/my_test.ftl" as my&gt;<br />${my.mail}<br />&lt;#assign mail="<a href="mailto:jsmith@other.com">jsmith@other.com</a>" in my&gt;<br />${my.mail}<br />输出结果：<br /><a href="mailto:jsmith@acme.com">jsmith@acme.com</a><br /><a href="mailto:jsmith@other.com">jsmith@other.com</a><br />数据模型中的变量任何地方都可见，也包括不同的名字空间，下面是修改的库：<br />&lt;#macro copyright date&gt;<br />  &lt;p&gt;Copyright (C) ${date} ${user}. All rights reserved.&lt;/p&gt;<br />&lt;/#macro&gt;<br />&lt;#assign mail = "<a href="mailto:$%7Buser%7D@acme.com">mailto:$%7Buser%7D@acme.com</a>"&gt;<br />假设数据模型中的user变量的值是Fred，则下面的代码：<br />&lt;#import "/lib/my_test.ftl" as my&gt;<br />&lt;@my.copyright date="1999-2002"/&gt;<br />${my.mail}<br />输出结果：<br />&lt;p&gt;Copyright (C) 1999-2002 Fred. All rights reserved.&lt;/p&gt;Fred@acme.com</p>
		<p>
		</p>
		<p>
				<br />----------------------------------------------------------------------------<br /><strong><font size="5">四．Freemarker与Struts结合</font></strong></p>
		<p>1.输出文件换成以ftl格式的文件</p>
		<p>E.G.</p>
		<p>&lt;action name="bookActionForm" parameter="method" path="/bookAction" scope="request" type="example.BookAction" </p>
		<p>validate="true"&gt;</p>
		<p>&lt;forward name="list" path="/index.ftl"/&gt;</p>
		<p>&lt;/action&gt;</p>
		<p>2.使用struts，jstl等标签</p>
		<p>a.导入à&lt;#global html=JspTaglibs["/WEB-INF/tags/struts-html.tld"]&gt;</p>
		<p>或&lt;#assign html=JspTaglibs["/WEB-INF/struts-html.tld"]&gt;<br />&lt;#assign bean=JspTaglibs["/WEB-INF/struts-bean.tld"]&gt;<br />&lt;#assign logic=JspTaglibs["/WEB-INF/struts-logic.tld"]&gt;</p>
		<p>b.使用à&lt;@bean.page id="request" property="request"/&gt;,<br />&lt;@html.text property="vo.newsTitle" styleClass="input1"/&gt;<br /></p>
		<p>
				<font size="5">
						<font size="3">----------------------------------------------------------------------------</font>
						<br />
						<strong>五．用Freemarker生成Html页面</strong>
				</font>
		</p>
		<p>   例子：MakeFileManager.java</p>
		<p> </p>
		<p>package example;</p>
		<p>import freemarker.template.Configuration;<br />import java.text.SimpleDateFormat;<br />import java.io.File;<br />import freemarker.template.DefaultObjectWrapper;<br />import java.util.Map;<br />import java.util.HashMap;<br />import java.io.Writer;<br />import java.io.OutputStreamWriter;<br />import java.io.FileOutputStream;<br />import freemarker.template.TemplateException;<br />import java.io.IOException;<br />import freemarker.template.Template;</p>
		<p>public class MakeFileManager {<br />    public String make(Book book, BookFtl bookFtl) {<br />        Configuration cfg = new Configuration();//配制</p>
		<p>        String realPath = bookFtl.getRealPath();<br />        String templatePath = realPath + "/WEB-INF/templates/book";<br />        String cDateStr = "book/" +<br />                          new SimpleDateFormat("yyyyMMdd").format(new java.util.<br />                Date());<br />        String filePostfix = ".html";<br />        String path = realPath + "/" + cDateStr;<br />        String fileTimeName = new SimpleDateFormat("yyyyMMddhhmmss").format(new<br />                java.util.Date());<br />        String returnFileName = cDateStr + "/" + fileTimeName + filePostfix;<br />        String fileName = "";<br />        File bookDir = new File(path);<br />        if (bookDir.exists()) {<br />            fileName = path + "/" + fileTimeName + filePostfix;<br />        } else {<br />            bookDir.mkdirs();<br />            fileName = path + "/" + fileTimeName + filePostfix;<br />        }<br />        try {<br />            //设置freemarker的参数<br />            cfg.setNumberFormat("0.##########");//生成html文件时web.xml配制无效<br />            //cfg.setEncoding();<br />            cfg.setDirectoryForTemplateLoading(new File(templatePath));<br />            cfg.setObjectWrapper(new DefaultObjectWrapper());<br />            Template bookTemplate = cfg.getTemplate(bookFtl.getTemplateName());//模板对象<br />            Map root = new HashMap();<br />            root.put("book", book);<br />            root.put("book2",book);<br />            Writer out = new OutputStreamWriter(new FileOutputStream(fileName));<br />            try {<br />                bookTemplate.process(root, out);<br />            } catch (TemplateException e) {<br />                e.printStackTrace();<br />            }<br />            out.flush();<br />        } catch (IOException e) {<br />            e.printStackTrace();<br />        }<br />        return returnFileName;<br />    }<br />}</p>
<img src ="http://www.blogjava.net/wjywilliam/aggbug/351928.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wjywilliam/" target="_blank">wjywilliam</a> 2011-06-08 17:46 <a href="http://www.blogjava.net/wjywilliam/articles/351928.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OGNL, JSTL, STRUTS2标签用法示例</title><link>http://www.blogjava.net/wjywilliam/articles/349036.html</link><dc:creator>wjywilliam</dc:creator><author>wjywilliam</author><pubDate>Tue, 26 Apr 2011 06:24:00 GMT</pubDate><guid>http://www.blogjava.net/wjywilliam/articles/349036.html</guid><wfw:comment>http://www.blogjava.net/wjywilliam/comments/349036.html</wfw:comment><comments>http://www.blogjava.net/wjywilliam/articles/349036.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wjywilliam/comments/commentRss/349036.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wjywilliam/services/trackbacks/349036.html</trackback:ping><description><![CDATA[
		<div>
				<div>
						<strong>OGNL, JSTL, STRUTS2标签用法示例 （转载） <br /></strong>
						<br />
						<strong>取Session中的值</strong>
				</div>
				<div>&lt;c:out value="${sessionScope.user.userId}"&gt;&lt;/c:out&gt;&lt;br&gt;   </div>
				<div>&lt;c:out value="${user.userLoginName}"&gt;&lt;/c:out&gt;&lt;br&gt;     </div>
				<div>&lt;s:property value="#session.user.userId"/&gt;&lt;br&gt;   </div>
				<div>${session.user.userId}&lt;br&gt;  </div>${sessionScope.user.userId}&lt;br&gt;     <br /><div><div g_c_pdin="" g_p_center="" c07="" content?=""><div><strong>基本语法</strong></div><div><strong>一、EL简介<br /></strong>  <strong>1.语法结构<br /></strong>    ${expression}<br />  <strong>2.[]与.运算符<br /></strong>    EL 提供.和[]两种运算符来存取数据。<br />    当要存取的属性名称中包含一些特殊字符，如.或?等并非字母或数字的符号，就一定要使用 []。例如：<br />        ${user.My-Name}应当改为${user["My-Name"] }<br />    如果要动态取值时，就可以用[]来做，而.无法做到动态取值。例如：<br />        ${sessionScope.user[data]}中data 是一个变量<br />  <strong>3.变量<br /></strong>    EL存取变量数据的方法很简单，例如：${username}。它的意思是取出某一范围中名称为username的变量。<br />    因为我们并没有指定哪一个范围的username，所以它会依序从Page、Request、Session、Application范围查找。<br />    假如途中找到username，就直接回传，不再继续找下去，但是假如全部的范围都没有找到时，就回传null。<br />    属性范围在EL中的名称<br />        Page              pageScope<br />        Request          requestScope<br />        Session           sessionScope<br />        Application     applicationScope<br />        <br /><strong>二、EL隐含对象<br /></strong>  <strong>1.与范围有关的隐含对象<br /></strong>  与范围有关的EL 隐含对象包含以下四个：pageScope、requestScope、sessionScope 和applicationScope；<br />  它们基本上就和JSP的pageContext、request、session和application一样；<br />  在EL中，这四个隐含对象只能用来取得范围属性值，即getAttribute(String name)，却不能取得其他相关信息。<br />  <br />  例如：我们要取得session中储存一个属性username的值，可以利用下列方法：<br />    session.getAttribute("username") 取得username的值，<br />  在EL中则使用下列方法<br />    ${sessionScope.username}</div><div>  <strong>2.与输入有关的隐含对象<br /></strong>  与输入有关的隐含对象有两个：param和paramValues，它们是EL中比较特别的隐含对象。<br />  <br />  例如我们要取得用户的请求参数时，可以利用下列方法：<br />    request.getParameter(String name)<br />    request.getParameterValues(String name)<br />  在EL中则可以使用param和paramValues两者来取得数据。<br />    ${param.name}<br />    ${paramValues.name}<br /></div><div><br />  <strong>3.其他隐含对象</strong>  <br />  cookie<br />  JSTL并没有提供设定cookie的动作，<br />  例：要取得cookie中有一个设定名称为userCountry的值，可以使用${cookie.userCountry}来取得它。</div><div>  header和headerValues<br />  header 储存用户浏览器和服务端用来沟通的数据<br />  例：要取得用户浏览器的版本，可以使用${header["User-Agent"]}。<br />  另外在鲜少机会下，有可能同一标头名称拥有不同的值，此时必须改为使用headerValues 来取得这些值。</div><div>  initParam<br />  initParam取得设定web站点的环境参数(Context)<br />  例：一般的方法String userid = (String)application.getInitParameter("userid");<br />    可以使用 ${initParam.userid}来取得名称为userid</div><div>  pageContext<br />  pageContext取得其他有关用户要求或页面的详细信息。<br />    ${pageContext.request.queryString}         取得请求的参数字符串<br />    ${pageContext.request.requestURL}         取得请求的URL，但不包括请求之参数字符串<br />    ${pageContext.request.contextPath}         服务的web application 的名称<br />    ${pageContext.request.method}           取得HTTP 的方法(GET、POST)<br />    ${pageContext.request.protocol}         取得使用的协议(HTTP/1.1、HTTP/1.0)<br />    ${pageContext.request.remoteUser}         取得用户名称<br />    ${pageContext.request.remoteAddr }         取得用户的IP 地址<br />    ${pageContext.session.new}             判断session 是否为新的<br />    ${pageContext.session.id}               取得session 的ID<br />    ${pageContext.servletContext.serverInfo}   取得主机端的服务信息<br /></div><div><br /><strong>三、EL运算符</strong><br />  1.算术运算符有五个：+、-、*或$、/或div、%或mod<br />  2.关系运算符有六个：==或eq、!=或ne、&lt;或lt、&gt;或gt、&lt;=或le、&gt;=或ge<br />  3.逻辑运算符有三个：&amp;&amp;或and、||或or、!或not<br />  4.其它运算符有三个：Empty运算符、条件运算符、()运算符<br />    例：${empty param.name}、${A?B:C}、${A*(B+C)}<br />  <br /><strong>四、EL函数(functions)<br /></strong>  语法：ns:function( arg1, arg2, arg3 …. argN)<br />  其中ns为前置名称(prefix)，它必须和taglib 指令的前置名称一置</div><div>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</div><div><strong>补充：</strong></div><div>&lt;%@ taglib prefix="c" uri="<a href="http://java.sun.com/jstl/core_rt"><font color="#37708b">http://java.sun.com/jstl/core_rt</font></a>" %&gt;</div><div>FOREACH:</div><div>&lt;c:forEach items="${messages}"<br />var="item"<br />begin="0"<br />end="9"<br />step="1"<br />varStatus="var"&gt;<br />……<br />&lt;/c:forEach&gt;</div><div> </div><div><br />OUT:</div><div>&lt;c:out value="${logininfo.username}"/&gt;<br />c:out&gt;将value 中的内容输出到当前位置，这里也就是把logininfo 对象的<br />username属性值输出到页面当前位置。<br />${……}是JSP2.0 中的Expression Language（EL）的语法。它定义了一个表达式，<br />其中的表达式可以是一个常量（如上），也可以是一个具体的表达语句（如forEach循环体中<br />的情况）。典型案例如下：<br />? ${logininfo.username}<br />这表明引用logininfo 对象的username 属性。我们可以通过“.”操作符引<br />用对象的属性，也可以用“[]”引用对象属性，如${logininfo[username]}<br />与${logininfo.username}达到了同样的效果。<br />“[]”引用方式的意义在于，如果属性名中出现了特殊字符，如“.”或者“-”，<br />此时就必须使用“[]”获取属性值以避免语法上的冲突（系统开发时应尽量避免<br />这一现象的出现）。<br />与之等同的JSP Script大致如下：<br />LoginInfo logininfo =<br />(LoginInfo)session.getAttribute(“logininfo”);<br />String username = logininfo.getUsername();<br />可以看到，EL大大节省了编码量。<br />这里引出的另外一个问题就是，EL 将从哪里找到logininfo 对象，对于<br />${logininfo.username}这样的表达式而言，首先会从当前页面中寻找之前是<br />否定义了变量logininfo，如果没有找到则依次到Request、Session、<br />Application 范围内寻找，直到找到为止。如果直到最后依然没有找到匹配的<br />变量，则返回null.<br />如果我们需要指定变量的寻找范围，可以在EL表达式中指定搜寻范围：<br />${pageScope.logininfo.username}<br />${requestScope.logininfo.username}<br />${sessionScope.logininfo.username}<br />${applicationScope.logininfo.username}<br />在Spring 中，所有逻辑处理单元返回的结果数据，都将作为Attribute 被放<br />置到HttpServletRequest 对象中返回（具体实现可参见Spring 源码中<br />org.springframework.web.servlet.view.InternalResourceView.<br />exposeModelAsRequestAttributes方法的实现代码），也就是说Spring<br />MVC 中，结果数据对象默认都是requestScope。因此，在Spring MVC 中，<br />以下寻址方法应慎用：<br />${sessionScope.logininfo.username}<br />${applicationScope.logininfo.username}<br />? ${1＋2}<br />结果为表达式计算结果，即整数值3。<br />? ${i&gt;1}<br />如果变量值i&gt;1的话，将返回bool类型true。与上例比较，可以发现EL会自<br />动根据表达式计算结果返回不同的数据类型。<br />表达式的写法与java代码中的表达式编写方式大致相同。</div><div> </div><div>IF / CHOOSE:</div><div>&lt;c:if test="${var.index % 2 == 0}"&gt;<br />*<br />&lt;/c:if&gt;<br />判定条件一般为一个EL表达式。<br />&lt;c:if&gt;并没有提供else子句，使用的时候可能有些不便，此时我们可以通过&lt;c:choose&gt;<br />tag来达到类似的目的：<br />&lt;c:choose&gt;<br />&lt;c:when test="${var.index % 2 == 0}"&gt;<br />*<br />&lt;/c:when&gt;<br />&lt;c:otherwise&gt;<br />!<br />&lt;/c:otherwise&gt;<br />&lt;/c:choose&gt;<br />类似Java 中的switch 语句，&lt;c:choose&gt;提供了复杂判定条件下的简化处理手法。其<br />中&lt;c:when&gt;子句类似case子句，可以出现多次。上面的代码，在奇数行时输出“*”号，<br />而偶数行时输出“!”。<br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</div><div><strong>再补充：</strong></div><div> 1    EL表达式用${}表示,可用在所有的HTML和JSP标签中 作用是代替JSP页面中复杂的JAVA代码.</div><div>        2   EL表达式可操作常量 变量 和隐式对象. 最常用的 隐式对象有${param}和${paramValues}. ${param}表示返回请求参数中单个字符串的值. ${paramValues}表示返回请求参数的一组值.pageScope表示页面范围的变量.requestScope表示请求对象的变量. sessionScope表示会话范围内的变量.applicationScope表示应用范围的变量.</div><div>        3   &lt;%@  page isELIgnored="true"%&gt; 表示是否禁用EL语言,TRUE表示禁止.FALSE表示不禁止.JSP2.0中默认的启用EL语言.</div><div>        4   EL语言可显示 逻辑表达式如${true and false}结果是false    关系表达式如${5&gt;6} 结果是false     算术表达式如 ${5+5} 结果是10</div><div>        5   EL中的变量搜索范围是:page request session application   点运算符(.)和"[ ]"都是表示获取变量的值.区别是[ ]可以显示非词类的变量</div></div></div><div> </div><div> </div><div> </div><div> </div><div><strong>OGNL</strong></div><div>OGNL是Object Graph Navigation Language的简称，详细相关的信息可以参考：<a href="http://www.ognl.org/"><font color="#1848b5">http://www.ognl.org</font></a>。这里我们只涉及Struts2框架中对OGNL的基本支持。</div><div> </div><div>OGNL是一个对象，属性的查询语言。在OGNL中有一个类型为Map的Context（称为上下文），在这个上下文中有一个根元素（root），对根元素的属性的访问可以直接使用属性名字，但是对于其他非根元素属性的访问必须加上特殊符号#。</div><div> </div><div>在Struts2中上下文为ActionContext，根元素位Value Stack（值堆栈，值堆栈代表了一族对象而不是一个对象，其中Action类的实例也属于值堆栈的一个）。ActionContext中的内容如下图：</div><div>              |</div><div>              |--application</div><div>              |</div><div>              |--session</div><div>context map---|</div><div>              |--value stack(root)</div><div>              |</div><div>              |--request</div><div>              |</div><div>              |--parameters</div><div>              |</div><div>              |--attr (searches page, request, session, then application scopes)</div><div>              |</div><div>因为Action实例被放在Value Stack中，而Value Stack又是根元素（root）中的一个，所以对Action中的属性的访问可以不使用标记#，而对其他的访问都必须使用#标记。</div><div> </div><div>引用Action的属性</div><div>&lt;s:property value="postalCode"/&gt;</div><div>ActionContext中的其他非根（root）元素的属性可以按照如下的方式访问：</div><div>&lt;s:property value="#session.mySessionPropKey"/&gt; or</div><div>&lt;s:property value="#session["mySessionPropKey"]"/&gt; or</div><div>&lt;s:property value="#request["mySessionPropKey"]/&gt;</div><div> </div><div>Action类可以使用ActionContext中的静态方法来访问ActionContext。</div><div>ActionContext.getContext().getSession().put("mySessionPropKey", mySessionObject);</div><div> </div><div>OGNL与Collection（Lists，Maps，Sets）</div><div> </div><div>生成List的语法为: {e1,e2,e3}.</div><div>&lt;s:select label="label" name="name" </div><div>list="{'name1','name2','name3'}" value="%{'name2'}" /&gt;</div><div>上面的代码生成了一个HTML Select对象，可选的内容为： name1，name2，name3，默认值为：name2。</div><div> </div><div>生成Map的语法为：#{key1:value1,key2:value2}.</div><div>&lt;s:select label="label" name="name" </div><div>list="#{'foo':'foovalue', 'bar':'barvalue'}" /&gt;</div><div>上面的代码生成了一个HTML Select对象,foo名字表示的内容为：foovalue，bar名字表示的内容为：barvalue。</div><div> </div><div>判断一个对象是否在List内存在：</div><div>&lt;s:if test="'foo' in {'foo','bar'}"&gt;</div><div>   muhahaha</div><div>&lt;/s:if&gt;</div><div>&lt;s:else&gt;</div><div>   boo</div><div>&lt;/s:else&gt;</div><div> </div><div>&lt;s:if test="'foo' not in {'foo','bar'}"&gt;</div><div>   muhahaha</div><div>&lt;/s:if&gt;</div><div>&lt;s:else&gt;</div><div>   boo</div><div>&lt;/s:else&gt;</div><div> </div><div>取得一个List的一部分：</div><div>?  –  所有满足选择逻辑的对象 </div><div>^  -   第一个满足选择逻辑的对象 </div><div>$  -   最后一个满足选择逻辑的对象</div><div>例如：</div><div>person.relatives.{? #this.gender == 'male'}</div><div>上述代码取得这个人（person）所有的男性（this.gender==male）的亲戚(relatives)</div><div> </div><div> </div><div><strong>Lambda 表达式</strong></div><div> </div><div>OGNL支持简单的Lambda表达式语法，使用这些语法可以建立简单的lambda函数。</div><div> </div><div>例如：</div><div>Fibonacci: </div><div>if n==0 return 0; </div><div>elseif n==1 return 1; </div><div>else return fib(n-2)+fib(n-1);</div><div>fib(0) = 0</div><div>fib(1) = 1</div><div>fib(11) = 89</div><div> </div><div>OGNL的Lambda表达式如何工作呢？</div><div>Lambda表达式必须放在方括号内部，#this表示表达式的参数。例如： </div><div>&lt;s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" /&gt;</div><div> </div><div>#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)]定义了一个Lambda表达式，</div><div>#fib(11) 调用了这个表达式。</div><div> </div><div>所以上述代码的输出为：89</div><div> </div><div>在JSP2.1中#被用作了JSP EL（表达式语言）的特殊记好，所以对OGNL的使用可能导致问题，</div><div>一个简单的方法是禁用JSP2.1的EL特性，这需要修改web.xml文件：</div><div>&lt;jsp-config&gt;</div><div>    &lt;jsp-property-group&gt;</div><div>      &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;</div><div>      &lt;el-ignored&gt;true&lt;/el-ignored&gt;</div><div>    &lt;/jsp-property-group&gt;</div><div>&lt;/jsp-config&gt;</div></div>
		<p> </p>
<img src ="http://www.blogjava.net/wjywilliam/aggbug/349036.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wjywilliam/" target="_blank">wjywilliam</a> 2011-04-26 14:24 <a href="http://www.blogjava.net/wjywilliam/articles/349036.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2: 在javascript中操作 datetimepicker 标签控件的值</title><link>http://www.blogjava.net/wjywilliam/articles/233919.html</link><dc:creator>wjywilliam</dc:creator><author>wjywilliam</author><pubDate>Sun, 12 Oct 2008 15:18:00 GMT</pubDate><guid>http://www.blogjava.net/wjywilliam/articles/233919.html</guid><wfw:comment>http://www.blogjava.net/wjywilliam/comments/233919.html</wfw:comment><comments>http://www.blogjava.net/wjywilliam/articles/233919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wjywilliam/comments/commentRss/233919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wjywilliam/services/trackbacks/233919.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;只有注册用户登录后才能阅读该文。<a href='http://www.blogjava.net/wjywilliam/articles/233919.html'>阅读全文</a><img src ="http://www.blogjava.net/wjywilliam/aggbug/233919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wjywilliam/" target="_blank">wjywilliam</a> 2008-10-12 23:18 <a href="http://www.blogjava.net/wjywilliam/articles/233919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>