??xml version="1.0" encoding="utf-8" standalone="yes"?>
二.环境搭徏与配|?/strong>
三.常用语法
四.与Strutsl合
五.生成Html面
一QFreemarker?br />
什么是Freemarker:.
Freemaker是一个”模板引擎?也可以说是一个基于模板技术的生成文本输出的一个通用工具.它是一个JAVA的包,一个JAVAE序员可以用的
cd.本nq不是一个对最l用L(fng)应用E序.但是,E序员可以把它应用到他们的品中.
FreeMarker是设计ؓ(f)可以生成WEB PAGES.它是ZSERVLET遵@MVC模式?q个思\是应用MVC模式要降低分?|页设计人员和程序员的耦合.
每个人都可以做他们擅长的工作.|页设计人员可以改变|页的面?而ƈ不需要程序员的重新编?因ؓ(f)业务逻辑和页面的设计已经被分d?/p>
.模板是不能由复杂的程序片断组成的.即便|页设计人员和程序员是一个h. 分离是有必要?它能使程序更加的灉|和清?
虽然Freemarker能编E?但是它ƈ不是一个编E语a.它是为程序显C数据而准备的.(像数据库SQL语句的查?)以及(qing).Freemarker仅仅是利用模
板加上数据生成文本页?
Freemarkerq不是一个WEB应用E序框架.可以说是一个WEB应用框架的一个组?但是FREEMARKER引擎本nq不?jin)解HTTP或者SERVLETS.它只不过
生成文本而已.注意,它是MVC框架的一个组?如STRUTS),也可以在模板中用JSP标签.
(tng) Freemarker下蝲地址为:(x)http://www.freemarker.org/index.html
一般的用?
l 能用来生成Q意格式的文本:HTML,XML,RTF,JAVA源码,{等.
l可以更好的嵌入到你的产品?轻量U的.q不需要servlet环境.不依赖javax.servlet.classes.
l可插入的模板d?你可以从L的源码读取Q意的模板.本地的文?数据库等{?
l你可以做L你想生成的文?存储为本地文?可以用来发送EMAIL或返回到WEB览器中.
(tng)
强大的模板语a
l完整的指?include,if/elseif/else,loop.
l 建立和修Ҏ(gu)板中的变?
l 能用复杂的表辑ּ在Q意地Ҏ(gu)定变?
n字符串操?concateration,sub-string,uppercase,capitalize,escaping.{等
n十进制数学计?
n BOOL
nd数组和相关的数组元素.
n可以自己dҎ(gu)的计方?
l宏指?/p>
l 命名I间用来创徏和维护宏指o(h)库或者把大的目分成许多模块.q不用担?j)命名冲H?br />
----------------------------------------------------------------------------
二.环境搭徏与配|?br />
<!—freemarker初始配置-->
(tng)
<servlet>
<servlet-name>freemarker</servlet-name>
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
<init-param>
<param-name>TemplatePath</param-name>
<param-value>/</param-value>
</init-param>
<init-param>
<param-name>NoCache</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>ContentType</param-name>
<param-value>text/html</param-value>
</init-param>
<init-param>
<param-name>template_update_delay</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>default_encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>locale</param-name>
<param-value>zh_CN </param-value>
</init-param>
<init-param>
<param-name>number_format</param-name>
<param-value>0.##########</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>freemarker</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>
(tng)
----------------------------------------------------------------------------
三.常用语法
(tng)EG.一个对象BOOK
(tng) 1.输出 ${book.name}
I值判断:(x)${book.name?if_exists },
${book.name?default(‘xxx?}//默认值xxx
${ book.name!"xxx"}//默认值xxx
日期格式Q?{book.date?string('yyyy-MM-dd')}
数字格式Q?{book?string.number}--20
${book?string.currency}--<#-- $20.00 -->
${book?string.percent}?lt;#-- 20% -->
插入布尔|(x)
<#assign foo=ture />
${foo?string("yes","no")} <#-- yes -->
(tng)
(tng)
(tng)
(tng)
2Q逻辑判断
a:
<#if condition>...
<#elseif condition2>...
<#elseif condition3>......
<#else>...
其中I值判断可以写?lt;#if book.name?? >
(tng)
</#if>
b:
<#switch value>
(tng) <#case refValue1>
(tng) (tng) (tng) ...
(tng) (tng) (tng) <#break>
(tng) <#case refValue2>
(tng) (tng) (tng) ...
(tng) (tng) (tng) <#break>
(tng) ...
(tng) <#case refValueN>
(tng) (tng) (tng) ...
(tng) (tng) (tng) <#break>
(tng) <#default>
(tng) (tng) (tng) ...
</#switch>
(tng)
3Q@环读?br /><#list sequence as item>
...
</#list>
I值判?lt;#if bookList?size = 0></#list>
e.g.
<#list employees as e>
${e_index}. ${e.name}
</#list>
输出:
1. Readonly
2. Robbin
4.FreeMarker
4 (tng)?模板
宏Macro
宏是在模板中使用macro指o(h)定义
l.1 基本用法
宏是和某个变量关联的模板片断Q以便在模板中通过用户定义指o(h)使用该变量,下面是一个例子:(x)
<#macro greet>
(tng) <font size="+2">Hello Joe!</font>
</#macro>
调用宏时Q与使用FreeMarker的其他指令类|
(tng)只是使用@替代FTL标记中的#?/strong>
<@greet></@greet>
<#--<@greet/>-->
<#macro greet person>
可以q样使用该宏变量Q其中参数的ơ序是无关的Q?br /><@greet person="Fred" color="black"/> 可以在定义参数时指定~省|否则Q在调用宏的时候,必须Ҏ(gu)有参数赋|(x) 注意Q宏的参数是局部变量,只能在宏定义中有效?/p>
<#macro border> 执行宏调用:(x) <#nested>指o(h)可以被多ơ调用,每次都会(x)执行相同的内宏V?br /><#macro do_thrice>
FMPP 输出l果Q?br />Anything. 嵌套内容可以是有效的FTLQ下面是一个有些复杂的例子Q我们将上面三个宏组合v来:(x)
宏定义中的局部变量对嵌套内容是不可见?/strong>Q例如:(x) <@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat> 输出l果Q?br />test 3/1: ? ? ?
<@ macro_name paramter list; loop variable list[,]> 例如Q?br /><#macro repeat count> <@repeat count=4 ; c, halfc, last> q里count是宏的参敎ͼc, halfc,last则ؓ(f)循环变量Q输出结果:(x) 不会(x)被创建:(x) <@repeat count=4 ; c, halfc> <@repeat count=4>
在模板中定义变量 <#assign x = "plain"> <@test/> 模型中的user的值是Big JoeQ?br /><#assign user = "Joe Hider"> 其目的是防止同名冲突 Q下面是一个例子:(x)
1.输出文g换成以ftl格式的文?/p>
E.G. <action name="bookActionForm" parameter="method" path="/bookAction" scope="request" type="example.BookAction" validate="true"> <forward name="list" path="/index.ftl"/> </action> 2.使用strutsQjstl{标{?/p>
a.导入à<#global html=JspTaglibs["/WEB-INF/tags/struts-html.tld"]> ?lt;#assign html=JspTaglibs["/WEB-INF/struts-html.tld"]> b.使用à<@bean.page id="request" property="request"/>,
----------------------------------------------------------------------------
(tng) (tng) 例子QMakeFileManager.java (tng) package example; import freemarker.template.Configuration; public class MakeFileManager { (tng) (tng) (tng) (tng) (tng) (tng) (tng) String realPath = bookFtl.getRealPath(); (tng)
在macro指o(h)中可以在宏变量之后定义参?/strong>Q如Q?/p>
(tng) <font size="+2">Hello ${person}!</font>
</#macro>
(tng)可以q样使用q个宏变量:(x)
(tng) (tng)<@greet person="Fred"/>
(tng)但是下面的代码具有不同的意思:(x)
(tng) (tng)<@greet person=Fred/>
(tng)q意味着Fred变量的glperson参数Q该g仅是字符Ԍq可以是其它cdQ甚x(chng)复杂的表辑ּ?/p>
宏可以有多参敎ͼ下面是一个例?/strong>Q?br /><#macro greet person color>
(tng) <font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
<#macro greet person color="black">
(tng) <font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
在宏里嵌套内?br />FreeMarker的宏可以有嵌套内容,
<#nested>指o(h)?x)执行宏调用指o(h)开始和l束标记之间的模板片断,举一个简单的例子Q?/p>
(tng) <table border=4 cellspacing=0 cellpadding=4><tr><td>
(tng) (tng) (tng) <#nested>
(tng) </tr></td></table>
</#macro>
<@border>The bordered text</@border>
输出l果Q?br /><table border=4 cellspacing=0 cellpadding=4>
(tng)<tr><td>
(tng) (tng) (tng) (tng) (tng)The bordered text
(tng) (tng)</tr></td>
</table>
(tng) <#nested>
(tng) <#nested>
(tng) <#nested>
</#macro>
<@do_thrice>
(tng) Anything.
</@do_thrice>
Anything.
Anything.
<@border>
(tng) <ul>
(tng) <@do_thrice>
(tng) (tng) (tng) <li><@greet person="Joe"/>
(tng) </@do_thrice>
(tng) </ul>
</@border>
输出l果Q?br /><table border=4 cellspacing=0 cellpadding=4><tr><td>
(tng) <ul>
(tng) (tng) (tng) <li><font size="+2">Hello Joe!</font>
(tng) (tng) (tng) <li><font size="+2">Hello Joe!</font>
(tng) (tng) (tng) <li><font size="+2">Hello Joe!</font>
(tng) </ul>
(tng) </tr></td></table>
<#macro repeat count>
(tng) <#local y = "test">
(tng) <#list 1..count as x>
(tng) (tng) (tng) ${y} ${count}/${x}: <#nested>
(tng) </#list>
</#macro>
test 3/2: ? ? ?
test 3/3: ? ? ?
在宏定义中用@环变?br />nestted指o(h)也可以有循环变量Q@环变量的含义见下节)(j)Q调用宏的时候在宏指令的参数后面依次列出循环变量的名字,格式如下Q?/p>
(tng) <#list 1..count as x>
(tng) (tng) (tng) <#nested x, x/2, x==count>
(tng) </#list>
</#macro>
(tng) ${c}. ${halfc}<#if last> Last!</#if>
</@repeat>
(tng) 1. 0.5
(tng) 2. 1
(tng) 3. 1.5
(tng) 4. 2 Last!
循环变量和宏标记指定的不同不?x)有问题Q如果调用时指定了(jin)循环变量Q那么多余的g可见。调用时多指定了(jin)循环变量Q多余的循环变量
<@repeat count=4 ; c, halfc, last>
(tng) ${c}. ${halfc}<#if last> Last!</#if>
</@repeat>
(tng) ${c}. ${halfc}
</@repeat>
(tng) Just repeat it...
</@repeat>
在模板中定义的变量有三种cdQ?br />plain变量Q可以在模板的Q何地方访问,包括使用include指o(h)插入的模板,使用assign指o(h)创徏和替换?br />局部变量:(x)在宏定义体中有效Q用local指o(h)创徏和替换?br />循环变量Q只能存在于指o(h)的嵌套内容,由指令(如listQ自动创建;宏的参数是局部变量,而不是@环变?br />局部变量隐藏(而不是覆盖)(j)同名的plain变量Q@环变量隐藏同名的局部变量和plain变量Q下面是一个例子:(x)
(tng)
${x} (tng) <#-- we see the plain var. here -->
(tng) 6. ${x} (tng) <#-- the value of plain var. was not changed -->
(tng) <#list ["loop"] as x>
(tng) 7. ${x} (tng) <#-- now the loop var. hides the plain var. -->
(tng) (tng) (tng) <#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
(tng) 8. ${x} (tng) <#-- it still hides the plain var. -->
(tng) </#list>
(tng) 9. ${x} (tng) <#-- the new value of plain var. -->
(tng) <#macro test>
(tng) 2. ${x} (tng) <#-- we still see the plain var. here -->
(tng) <#local x = "local">
(tng) 3. ${x} (tng) <#-- now the local var. hides it -->
(tng) <#list ["loop"] as x>
(tng) (tng) (tng) 4. ${x} (tng) <#-- now the loop var. hides the local var. -->
(tng) </#list>
(tng) 5. ${x} (tng) <#-- now we see the local var. again -->
</#macro>
输出l果Q?br /> (tng) 1. plain
(tng) 2. plain
(tng) 3. local
(tng) 4. loop
(tng) 5. local
(tng) 6. plain
(tng) 7. loop
(tng) 8. loop
(tng) 9. plain2
内部循环变量隐藏同名的外部@环变量,如:(x)
<#list ["loop 1"] as x>
(tng) ${x}
(tng) <#list ["loop 2"] as x>
(tng) (tng) (tng) ${x}
(tng) (tng) (tng) <#list ["loop 3"] as x>
(tng) (tng) (tng) (tng) (tng) ${x}
(tng) (tng) (tng) </#list>
(tng) (tng) (tng) ${x}
(tng) </#list>
(tng) ${x}
</#list>
输出l果Q?br />loop 1
(tng) (tng) (tng) loop 2
(tng) (tng) (tng) (tng) (tng) loop 3
(tng) (tng) (tng) loop 2
(tng) loop 1
模板中的变量?x)隐藏(而不是覆盖)(j)数据模型中同名变量,如果需要访问数据模型中的同名变量,使用Ҏ(gu)变量globalQ下面的例子假设数据
${user} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <#-- prints: Joe Hider -->
${.globals.user} <#-- prints: Big Joe -->
名字I间
通常情况Q只使用一个名字空_(d)UCؓ(f)d字空_(d)但ؓ(f)?jin)创建可重用的宏、变换器或其它变量的集合Q通常U库Q,必须使用多名字空_(d)
创徏?br />下面是一个创建库的例子(假设保存在lib/my_test.ftl中)(j)Q?br /><#macro copyright date>
(tng) <p>Copyright (C) ${date} Julia Smith. All rights reserved.
(tng) <br>Email: ${mail}</p>
</#macro>
<#assign mail = "jsmith@acme.com">
使用import指o(h)导入库到模板中,Freemarker?x)?f)导入的库创徏新的名字I间Qƈ可以通过import指o(h)中指定的散列变量讉K库中的变量:(x)
<#import "/lib/my_test.ftl" as my>
<#assign mail="fred@acme.com">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}
输出l果Q?br /><p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
(tng) <br>Email: mailto:jsmith@acme.com%3C/p>
jsmith@acme.com
fred@acme.com
可以看到例子中用的两个同名变量q没有冲H,因ؓ(f)它们位于不同的名字空间。还可以使用assign指o(h)在导入的名字I间中创建或替代变量
<#import "/lib/my_test.ftl" as my>
${my.mail}
<#assign mail="jsmith@other.com" in my>
${my.mail}
输出l果Q?br />jsmith@acme.com
jsmith@other.com
数据模型中的变量M地方都可见,也包括不同的名字I间Q下面是修改的库Q?br /><#macro copyright date>
(tng) <p>Copyright (C) ${date} ${user}. All rights reserved.</p>
</#macro>
<#assign mail = "mailto:$%7Buser%7D@acme.com">
假设数据模型中的user变量的值是FredQ则下面的代码:(x)
<#import "/lib/my_test.ftl" as my>
<@my.copyright date="1999-2002"/>
${my.mail}
输出l果Q?br /><p>Copyright (C) 1999-2002 Fred. All rights reserved.</p>Fred@acme.com
----------------------------------------------------------------------------
四.Freemarker与Strutsl合
<#assign bean=JspTaglibs["/WEB-INF/struts-bean.tld"]>
<#assign logic=JspTaglibs["/WEB-INF/struts-logic.tld"]>
<@html.text property="vo.newsTitle" styleClass="input1"/>
五.用Freemarker生成Html面
import java.text.SimpleDateFormat;
import java.io.File;
import freemarker.template.DefaultObjectWrapper;
import java.util.Map;
import java.util.HashMap;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import freemarker.template.TemplateException;
import java.io.IOException;
import freemarker.template.Template;
(tng) (tng) (tng) public String make(Book book, BookFtl bookFtl) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) Configuration cfg = new Configuration();//配制
(tng) (tng) (tng) (tng) (tng) (tng) (tng) String templatePath = realPath + "/WEB-INF/templates/book";
(tng) (tng) (tng) (tng) (tng) (tng) (tng) String cDateStr = "book/" +
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) new SimpleDateFormat("yyyyMMdd").format(new java.util.
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Date());
(tng) (tng) (tng) (tng) (tng) (tng) (tng) String filePostfix = ".html";
(tng) (tng) (tng) (tng) (tng) (tng) (tng) String path = realPath + "/" + cDateStr;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) String fileTimeName = new SimpleDateFormat("yyyyMMddhhmmss").format(new
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) java.util.Date());
(tng) (tng) (tng) (tng) (tng) (tng) (tng) String returnFileName = cDateStr + "/" + fileTimeName + filePostfix;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) String fileName = "";
(tng) (tng) (tng) (tng) (tng) (tng) (tng) File bookDir = new File(path);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) if (bookDir.exists()) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) fileName = path + "/" + fileTimeName + filePostfix;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) } else {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) bookDir.mkdirs();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) fileName = path + "/" + fileTimeName + filePostfix;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) }
(tng) (tng) (tng) (tng) (tng) (tng) (tng) try {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //讄freemarker的参?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) cfg.setNumberFormat("0.##########");//生成html文g时web.xml配制无效
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //cfg.setEncoding();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) cfg.setDirectoryForTemplateLoading(new File(templatePath));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) cfg.setObjectWrapper(new DefaultObjectWrapper());
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Template bookTemplate = cfg.getTemplate(bookFtl.getTemplateName());//模板对象
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Map root = new HashMap();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) root.put("book", book);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) root.put("book2",book);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Writer out = new OutputStreamWriter(new FileOutputStream(fileName));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) try {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) bookTemplate.process(root, out);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) } catch (TemplateException e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) out.flush();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) } catch (IOException e) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) e.printStackTrace();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) }
(tng) (tng) (tng) (tng) (tng) (tng) (tng) return returnFileName;
(tng) (tng) (tng) }
}
取Session中的?/strong>
(tng) (tng) (tng) ${expression}
(tng) 2.[]?q算W?br /> (tng) (tng) (tng) EL 提供.和[]两种q算W来存取数据?br /> (tng) (tng) (tng) 当要存取的属性名UC包含一些特D字W,??{ƈ非字母或数字的符P׃定要使用 []。例如:(x)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) ${user.My-Name}应当改ؓ(f)${user["My-Name"] }
(tng) (tng) (tng) 如果要动态取值时Q就可以用[]来做Q?无法做到动态取倹{例如:(x)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) ${sessionScope.user[data]}中data 是一个变?br /> (tng) 3.变量
(tng) (tng) (tng) EL存取变量数据的方法很单,例如Q?{username}。它的意思是取出某一范围中名UCؓ(f)username的变量?br /> (tng) (tng) (tng) 因ؓ(f)我们q没有指定哪一个范围的usernameQ所以它?x)依序从Page、Request、Session、Application范围查找?br /> (tng) (tng) (tng) 假如途中扑ֈusernameQ就直接回传Q不再l找下去Q但是假如全部的范围都没有找到时Q就回传null?br /> (tng) (tng) (tng) 属性范围在EL中的名称
(tng) (tng) (tng) (tng) (tng) (tng) (tng) Page (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)pageScope
(tng) (tng) (tng) (tng) (tng) (tng) (tng) Request (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) requestScope
(tng) (tng) (tng) (tng) (tng) (tng) (tng) Session (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) sessionScope
(tng) (tng) (tng) (tng) (tng) (tng) (tng) Application (tng) (tng) (tng) (tng) applicationScope
(tng) (tng) (tng) (tng) (tng) (tng) (tng)
二、EL隐含对象
(tng) 1.与范围有关的隐含对象
(tng) 与范围有关的EL 隐含对象包含以下四个QpageScope、requestScope、sessionScope 和applicationScopeQ?br /> (tng) 它们基本上就和JSP的pageContext、request、session和application一P
(tng) 在EL中,q四个隐含对象只能用来取得范围属性|即getAttribute(String name)Q却不能取得其他相关信息?br /> (tng)
(tng) 例如Q我们要取得session中储存(sh)个属性username的|可以利用下列Ҏ(gu)Q?br /> (tng) (tng) (tng) session.getAttribute("username") 取得username的|
(tng) 在EL中则使用下列Ҏ(gu)
(tng) (tng) (tng) ${sessionScope.username}
(tng) 与输入有关的隐含对象有两个:(x)param和paramValuesQ它们是EL中比较特别的隐含对象?br /> (tng)
(tng) 例如我们要取得用L(fng)h参数Ӟ可以利用下列Ҏ(gu)Q?br /> (tng) (tng) (tng) request.getParameter(String name)
(tng) (tng) (tng) request.getParameterValues(String name)
(tng) 在EL中则可以使用param和paramValues两者来取得数据?br /> (tng) (tng) (tng) ${param.name}
(tng) (tng) (tng) ${paramValues.name}
(tng) 3.其他隐含对象 (tng) (tng)
(tng) cookie
(tng) JSTLq没有提供设定cookie的动作,
(tng) 例:(x)要取得cookie中有一个设定名UCؓ(f)userCountry的|可以使用${cookie.userCountry}来取得它?/div>
(tng) header 储存用户览器和服务端用来沟通的数据
(tng) 例:(x)要取得用h览器的版本,可以使用${header["User-Agent"]}?br /> (tng) 另外在鲜机?x)下Q有可能同一标头名称拥有不同的|此时必须改ؓ(f)使用headerValues 来取得这些倹{?/div>
(tng) initParam取得讑֮web站点的环境参?Context)
(tng) 例:(x)一般的Ҏ(gu)String userid = (String)application.getInitParameter("userid");
(tng) (tng) (tng) 可以使用 ${initParam.userid}来取得名UCؓ(f)userid
(tng) pageContext取得其他有关用户要求或页面的详细信息?br /> (tng) (tng) (tng) ${pageContext.request.queryString} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 取得h的参数字W串
(tng) (tng) (tng) ${pageContext.request.requestURL} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 取得h的URLQ但不包括请求之参数字符?br /> (tng) (tng) (tng) ${pageContext.request.contextPath} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 服务的web application 的名U?br /> (tng) (tng) (tng) ${pageContext.request.method} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 取得HTTP 的方?GET、POST)
(tng) (tng) (tng) ${pageContext.request.protocol} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 取得使用的协?HTTP/1.1、HTTP/1.0)
(tng) (tng) (tng) ${pageContext.request.remoteUser} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 取得用户名称
(tng) (tng) (tng) ${pageContext.request.remoteAddr } (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 取得用户的IP 地址
(tng) (tng) (tng) ${pageContext.session.new} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 判断session 是否为新?br /> (tng) (tng) (tng) ${pageContext.session.id} (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 取得session 的ID
(tng) (tng) (tng) ${pageContext.servletContext.serverInfo} (tng) (tng) 取得L端的服务信息
三、ELq算W?/strong>
(tng) 1.术q算W有五个Q?????或div?或mod
(tng) 2.关系q算W有六个Q?=或eq?=或ne?lt;或lt?gt;或gt?lt;=或le?gt;=或ge
(tng) 3.逻辑q算W有三个Q?amp;&或and、||或or?或not
(tng) 4.其它q算W有三个QEmptyq算W、条件运符?)q算W?br /> (tng) (tng) (tng) 例:(x)${empty param.name}?{A?B:C}?{A*(B+C)}
(tng)
四、EL函数(functions)
(tng) 语法Qns:function( arg1, arg2, arg3 ? argN)
(tng) 其中ns为前|名U?prefix)Q它必须和taglib 指o(h)的前|名UC|?/div>
var="item"
begin="0"
end="9"
step="1"
varStatus="var">
…?br /></c:forEach>
OUT:
c:out>value 中的内容输出到当前位|,q里也就是把logininfo 对象?br />username属性D出到面当前位置?br />${……}是JSP2.0 中的Expression LanguageQELQ的语法。它定义?jin)一个表辑ּQ?br />其中的表辑ּ可以是一个常量(如上Q,也可以是一个具体的表达语句Q如forEach循环体中
的情况)(j)。典型案例如下:(x)
? ${logininfo.username}
q表明引用logininfo 对象的username 属性。我们可以通过?”操作符?br />用对象的属性,也可以用“[]”引用对象属性,?{logininfo[username]}
?{logininfo.username}辑ֈ?jin)同L(fng)效果?br />“[]”引用方式的意义在于Q如果属性名中出C(jin)Ҏ(gu)字符Q如?”或者?”,
此时必M用“[]”获取属性g避免语法上的冲突Q系l开发时应尽量避?br />q一现象的出玎ͼ(j)?br />与之{同的JSP Script大致如下Q?br />LoginInfo logininfo =
(LoginInfo)session.getAttribute(“logininfo?;
String username = logininfo.getUsername();
可以看到QEL大大节省?jin)编码量?br />q里引出的另外一个问题就是,EL 从哪里扑ֈl(f)ogininfo 对象Q对?br />${logininfo.username}q样的表辑ּ而言Q首先会(x)从当前页面中L之前?br />否定义了(jin)变量logininfoQ如果没有找到则依次到Request、Session?br />Application 范围内寻找,直到扑ֈ为止。如果直到最后依然没有找到匹配的
变量Q则q回null.
如果我们需要指定变量的L范围Q可以在EL表达式中指定搜寻范围Q?br />${pageScope.logininfo.username}
${requestScope.logininfo.username}
${sessionScope.logininfo.username}
${applicationScope.logininfo.username}
在Spring 中,所有逻辑处理单元q回的结果数据,都将作ؓ(f)Attribute 被放
|到HttpServletRequest 对象中返回(具体实现可参见Spring 源码?br />org.springframework.web.servlet.view.InternalResourceView.
exposeModelAsRequestAttributesҎ(gu)的实C码)(j)Q也是说Spring
MVC 中,l果数据对象默认都是requestScope。因此,在Spring MVC 中,
以下dҎ(gu)应慎用:(x)
${sessionScope.logininfo.username}
${applicationScope.logininfo.username}
? ${1Q?}
l果辑ּ计算l果Q即整数??br />? ${i>1}
如果变量值i>1的话Q将q回boolcdtrue。与上例比较Q可以发现EL?x)?br />动根据表辑ּ计算l果q回不同的数据类型?br />表达式的写法与java代码中的表达式编写方式大致相同?/div>
*
</c:if>
判定条g一般ؓ(f)一个EL表达式?br /><c:if>q没有提供else子句Q用的时候可能有些不便,此时我们可以通过<c:choose>
tag来达到类似的目的Q?br /><c:choose>
<c:when test="${var.index % 2 == 0}">
*
</c:when>
<c:otherwise>
!
</c:otherwise>
</c:choose>
cMJava 中的switch 语句Q?lt;c:choose>提供?jin)复杂判定条件下的简化处理手法。其
?lt;c:when>子句cMcase子句Q可以出现多ơ。上面的代码Q在奇数行时输出?”号Q?br />而偶数行时输出?”?br />Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?/div>