Struts2 标签库 [Tablib]
Struts2 Taglib
抽象了不同表示技术,现在Struts2 主要支持三种表示技术:JSP,FreeMarker 和Velocity 。但部分的Tag 在三种表示技术下都可以使用,但是也有部分只能在某一种情况下使用。
Tab
可以分为两类:通用标签和UI 标签。
4.1
节 通用标签
通用标签用来在页面表示的时候控制代码执行的过程,这些标签也允许从Action 或者值堆栈中取得数据。例如地域,JavaBeans ,URLs ,和action 。
控制标签控制程序执行,例如:if ,else,iterator
数据标签管理数据的取得和创建,例如:bean ,push,i18n
控制标签
if
标签
描述
If
标签用来控制基本的条件处理流程,通常和else 标签或者elseif 标签连用。
参数
名字
|
是否必须
|
默认值
|
可否使用表达式
|
类型
|
描述
|
id
|
否
|
|
是
|
String
|
用来表示该元素,对于UI 和Form 标签来说直接转变为HTML id 属性
|
test
|
是
|
|
是
|
Boolean
|
用来决定是否显示标签内部内容的表达式
|
例子
<s:if test="%{false}">
<div>Will Not Be Executed</div>
</s:if>
<s:elseif test="%{true}">
<div>Will Be Executed</div>
</s:elseif>
<s:else>
<div>Will Not Be Executed</div>
</s:else>
elseIf
标签
参考if 标签
else
标签
参考if 标签
append
标签
描述
用来做iterator 标签的辅助,将不同iterator 中的内容合在一个iterator 中。
参数
名字
|
是否必须
|
默认值
|
可否使用表达式
|
类型
|
描述
|
id
|
否
|
|
是
|
String
|
用来保存结果iterator 的对象在value context 中的名字。
|
例子
Action
类
public class AppendIteratorTagAction extends ActionSupport {
private List myList1;
private List myList2;
private List myList3;
public String execute() throws Exception {
myList1 = new ArrayList();
myList1.add("1");
myList1.add("2");
myList1.add("3");
myList2 = new ArrayList();
myList2.add("a");
myList2.add("b");
myList2.add("c");
myList3 = new ArrayList();
myList3.add("A");
myList3.add("B");
myList3.add("C");
return "done";
}
public List getMyList1() { return myList1; }
public List getMyList2() { return myList2; }
public List getMyList3() { return myList3; }
标签使用
<s:append id="myAppendIterator">
<s:param value="%{myList1}" />
<s:param value="%{myList2}" />
<s:param value="%{myList3}" />
</s:append>
<s:iterator value="%{#myAppendIterator}">
<s:property />
</s:iterator>
generator
标签(JSP Tag )
描述
从val 属性生成一个iterator 。
参数
例子
例1:
生成一个简单的iterator ,并且使用iterator 标签打印出内容。
<s:generator val="%{'aaa,bbb,ccc,ddd,eee'}">
<s:iterator>
<s:property /><br/>
</s:iterator>
</s:generator>
例2:
生成一个iterator ,使用count 属性。因为count 属性值为3 ,所以只有前三个内容(aaa,bbb,ccc )在生成的iterator 中。
Generate an iterator with count attribute
<s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" count="3">
<s:iterator>
<s:property /><br/>
</s:iterator>
</s:generator>
例3:
生成iterator ,使用了id 属性,之后生成的对象放在pageContext 中,可以通过指定的id 来访问。
<s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" count="4" separator="," id="myAtt" />
<%
Iterator i = (Iterator) pageContext.getAttribute("myAtt");
while(i.hasNext()) {
String s = (String) i.next();
%>
<%= s %> <br/>
<%
}
%>
例4:
生成iterator ,使用converter 属性,这里的convertor 仅仅将每一个对象添加了一个"converter-" 前缀。
<s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" converter="%{myConverter}">
<s:iterator>
<s:property /><br/>
</s:iterator>
</s:generator>
public class GeneratorTagAction extends ActionSupport {
....
public Converter getMyConverter() {
return new Converter() {
public Object convert(String value) throws Exception {
return "converter-"+value;
}
};
}
...
}
iterator
标签
描述
迭代处理一个java.util.Connection 或者java.util.Iterator 对象
参数
名字
|
是否必须
|
默认值
|
可否使用表达式
|
类型
|
描述
|
id
|
否
|
|
是
|
String
|
Id
,
|
status
|
否
|
否
|
是
|
Boolean
|
如果指定,在循环的过程中会保留一个IteratorStatus 类型的变量,该变量用来查询当前迭代的状态
|
value
|
否
|
|
是
|
String
|
被迭代的对象
|
例子
例1 :
<s:iterator value="days">
<p>day is: <s:property/></p>
</s:iterator>
例2 :
<s:bean name="org.apache.struts2.example.IteratorExample" id="it">
<s:param name="day" value="'foo'"/>
<s:param name="day" value="'bar'"/>
</s:bean>
<p/>
<table border="0" cellspacing="0" cellpadding="1">
<tr>
<th>Days of the week</th>
</tr>
<p/>
<s:iterator value="#it.days" status="rowstatus">
<tr>
<s:if test="#rowstatus.odd == true">
<td style="background: grey"><s:property/></td>
</s:if>
<s:else>
<td><s:property/></td>
</s:else>
</tr>
</s:iterator>
</table>
例3 :
<s:iterator value="groupDao.groups" status="groupStatus">
<tr
class="<s:if test="#groupStatus.odd == true ">odd</s:if><s:else>even</s:else>">
<td><s:property value="name" /></td>
<td><s:property value="description" /></td>
<td>
<s:iterator value="users" status="userStatus">
<s:property value="fullName" />
<s:if test="!#userStatus.last">,</s:if>
</s:iterator>
</td>
</tr>
</s:iterator>
merge
标签(同append ? )
描述
参数
例子
sort
标签(JSP-Tag )
描述
对一个可以迭代的对象进行排序操作。
参数
名字
|
是否必须
|
默认值
|
可否使用表达式
|
类型
|
描述
|
Comparator
|
是
|
|
是
|
java.util.Comparator
|
排序用的比较器
|
Source
|
否
|
|
是
|
String
|
排序对象
|
例子
例1:
<s:sort comparator="myComparator" source="myList">
<s:iterator>
<!-- do something with each sorted elements -->
<s:property value="..." />
</s:iterator>
</s:sort>
例2:
<s:sort id="mySortedList" comparator="myComparator" source="myList" />
<%
Iterator sortedIterator = (Iterator) pageContext.getAttribute("mySortedList");
for (Iterator i = sortedIterator; i.hasNext(); ) {
// do something with each of the sorted elements
}
%>
subset
描述
递归iterator 的一部分
参数
名字
|
是否必须
|
默认值
|
可否使用表达式
|
类型
|
描述
|
count
|
False
|
|
是
|
Integer
|
Iterator
中被递归的一部分的item 的数量
|
Decider
|
否
|
|
是
|
org.apache.struts2.util.
SubsetIteratorFilter.Decider
|
用来判断iterator 中的item 是否包含在最终的subset 内部
|
Source
|
否
|
|
是
|
String
|
Iterator
的对象
|
Start
|
否
|
|
是
|
Integer
|
开始位置
|
例子
Java
类
public class MySubsetTagAction extends ActionSupport {
public String execute() throws Exception {
l = new ArrayList();
l.add(new Integer(1));
l.add(new Integer(2));
l.add(new Integer(3));
l.add(new Integer(4));
l.add(new Integer(5));
return "done";
}
public Integer[] getMyArray() {
return a;
}
public List getMyList() {
return l;
}
public Decider getMyDecider() {
return new Decider() {
public boolean decide(Object element) throws Exception {
int i = ((Integer)element).intValue();
return (((i % 2) == 0)?true:false);
}
};
}
}
<!-- s: List basic -->
<s:subset source="myList">
<s:iterator>
<s:property />
</s:iterator>
</s:subset>
<!-- B: List with count -->
<s:subset source="myList" count="3">
<s:iterator>
<s:property />
</s:iterator>
</s:subset>
<!-- C: List with start -->
<s:subset source="myList" count="13" start="3">
<s:iterator>
<s:property />
</s:iterator>
</s:subset>
<!-- D: List with id -->
<s:subset id="mySubset" source="myList" count="13" start="3" />
<%
Iterator i = (Iterator) pageContext.getAttribute("mySubset");
while(i.hasNext()) {
%>
<%=i.next() %>
<% } %>
<!-- D: List with Decider -->
<s:subset source="myList" decider="myDecider">
<s:iterator>
<s:property />
</s:iterator>
</s:subset>
数据标签
@TODO
完成如下数据标签
数据标签包括
a
action
bean
date
debug
i18n
include
param
push
set
text
url
property
4.2
节 UI 标签
UI
标签主要是指Form 相关的标签,UI 标签又分为两部分:form 标签和构成form 内部字段的其他标签。
每一个UI 标签都是基于模板的,即:每一个标签都有一个对应的模板用来生成UI 标签的样式,详细内容参看模板节。
所有的UI 标签都有着共通的祖先UIBean ,UIBean 提供了这些UI 标签的一系列共通的属性,这些属性可以分为三类:模版相关的属性,JavaScript 相关的属性和其他通用属性。
模版相关属性:
属性
|
主题
|
数据类型
|
说明
|
templateDir
|
n/a
|
String
|
定义模版目录
|
theme
|
n/a
|
String
|
定义主题的名字
|
template
|
n/a
|
String
|
定义模版名字
|
JavaScript
相关属性:
属性
|
主题
|
数据类型
|
说明
|
onclick
|
simple
|
String
|
html javascript onclick
属性
|
ondbclick
|
simple
|
String
|
html javascript ondbclick
属性
|
onmousedown
|
simple
|
String
|
html javascript onmousedown
属性
|
onmouseup
|
simple
|
String
|
html javascript onmouseup
属性
|
onmouseover
|
simple
|
String
|
html javascript onmouseover
属性
|
onmouseout
|
simple
|
String
|
html javascript onmouseout
属性
|
onfocus
|
simple
|
String
|
html javascript onfocus
属性
|
onblur
|
simple
|
String
|
html javascript onblur
属性
|
onkeypress
|
simple
|
String
|
html javascript onkeypress
属性
|
onkeyup
|
simple
|
String
|
html javascript onkeyup
属性
|
onkeydown
|
simple
|
String
|
html javascript onkeydown
属性
|
onselect
|
simple
|
String
|
html javascript onselect
属性
|
onchange
|
simple
|
String
|
html javascript onchange
属性
|
Tooltip
相关属性:
属性
|
数据类型
|
默认值
|
说明
|
tooltip
|
String
|
none
|
为指定的组件设置Tooltip
|
jsTooltipEnabled
|
String
|
false
|
使用js 表示tooltip
|
tooltipIcon
|
String
|
/struts/static/tooltip/tooltip.gif
|
指向tooltip 图表的URL
|
tooltipDelay
|
String
|
500
|
多长时间后显示Tooltip
|
key
|
simple
|
String
|
这个输入字段对应的属性,用来自动设置name ,label 和value
|
通用属性:
属性
|
主题
|
数据类型
|
说明
|
cssClass
|
simple
|
String
|
定义html class 属性
|
cssStyle
|
simple
|
String
|
定义html style 属性
|
title
|
simple
|
String
|
定义html title 属性
|
disabled
|
simple
|
String
|
定义html disabled 属性
|
label
|
xhtml
|
String
|
定义form 字段的标签
|
labelPosition
|
xhtml
|
String
|
定义标签在Form 中的位置,从左从上计算
|
requiredPosition
|
xhtml
|
String
|
定义必须的标签在Form 中的位置,从左从上计算
|
name
|
simple
|
String
|
定义form 字段的name 映射
|
required
|
xhtml
|
Boolean
|
在label 上添加一个*
|
tabIndex
|
simple
|
String
|
定义 html tabIndex 属性
|
value
|
simple
|
Object
|
定义form 字段的值
|
对于name 和value 的说明:
name
用来说明Form 字段的名字,和Action 类的属性对应。
value
用来记录Form 字段的值,和Action 类中属性的值对应。
所以在修改一个字段的内容的时候应该使用如下的标签:
<s:form action="updateAddress">
<s:textfield label="Postal Code" name="postalCode" value="%{postalCode}"/>
...
</s:form>
但是,由于name 和value 的关系,struts2 标准标签可以自动对应,所以也可以使用如下标签:
<s:form action="updateAddress">
<s:textfield label="Postal Code" name="postalCode" />
...
</s:form>
UI
标签说明:
Form
部分
autocompleter
checkbox
checkboxlist
combobox
datetimepicker
doubleselect
head
file
form
hidden
label
optiontransferselect
optgroup
password
radio
reset
select
submit
textarea
textfield
token
updownselect
非Form 部分:
actionerror
actionmessage
component
div
fielderror
table
tabbedPanel
tree
treenode
4.3
节 主题和模板
概念说明:
标签(tag ):一小段代码,在JSP ,Velocity 或者FreeMarker 中执行。程序开发的最小单位,用来生成HTML 对应的元素。
模板(template ):一些代码,通常使用FreeMarker 写成,可以被某些Tag 表示出来(通常是UI Tag )。
主题(theme ):一组模板打包在一起,提供通用功能的模版
主题和模板主要针对可视化的标签(Tag )而言,使用以下例子来说明三者之间的关系。
假如我们要开发如下的一个画面:
我们使用如下的代码:
<
s:url
action
=
"login"
id
=
"loginUrl"
></
s:url
>
<
s:form
action
=
"%{loginUrl}"
>
<
s:textfield
label
=
"Name"
name
=
"name"
/>
<
s:password
label
=
"Password"
name
=
"password"
/>
<
s:submit
></
s:submit
>
<
s:reset
></
s:reset
>
</
s:form
>
这里
<
s:form
>
,
<
s:textfield
>
,
<
s:password
>
,
<
s:submit
>
,
<
s:reset
>
每一个都是一个标签(
tag
)。
我们在看看这些标签在一起生成的
HTML
源代码:
<
form
id
=
"login"
onsubmit
=
"return true;"
action
=
"/login/login/login.action"
method
=
"post"
>
<
table
class
=
"wwFormTable"
>
<
tr
>
<
td
class
=
"tdLabel"
>
<
label
for
=
"login_name"
class
=
"label"
>
Name:
</
label
>
</
td
>
<
td
>
<
input
type
=
"text"
name
=
"name"
value
=
""
id
=
"login_name"
/>
</
td
>
</
tr
>
<
tr
>
<
td
class
=
"tdLabel"
>
<
label
for
=
"login_password"
class
=
"label"
>
Password:
</
label
></
td
>
<
td
>
<
input
type
=
"password"
name
=
"password"
id
=
"login_password"
/>
</
td
>
</
tr
>
<
tr
>
<
td
colspan
=
"2"
>
<
div
align
=
"right"
><
input
type
=
"submit"
id
=
"login_0"
value
=
"Submit"
/></
div
>
</
td
>
</
tr
>
<
tr
>
<
td
colspan
=
"2"
>
<
div
align
=
"right"
><
input
type
=
"reset"
value
=
"Reset"
/></
div
>
</
td
>
</
tr
>
</
table
>
</
form
>
在由标签生成HTML 代码的时候,例如:
<
s:textfield
label
=
"Name"
name
=
"name"
/>
生成的代码为:
<
tr
>
<
td
class
=
"tdLabel"
>
<
label
for
=
"login_name"
class
=
"label"
>
Name:
</
label
>
</
td
>
<
td
>
<
input
type
=
"text"
name
=
"name"
value
=
""
id
=
"login_name"
/>
</
td
>
</
tr
>
我们可以看到,
<
s:textfield
>
标签提供的有效信息只有
Name
和
name
,而其余的部分,例如
<tr>
,
<td>
,
<label>
等代码都根据一个固定的模板文件生成,这个模板文件为:
标签使我们开发JSP 画面的时候使用的最小组件单元,我们根据客户的需要组合各种Tag 达到客户的需求。模板是生成这些Tag 时候使用的,使用模板可以定义Tag 的基本形式,在使用tag 的时候,我们只需要指定该Tag 的不同属性,即可根据Tag 指定的特殊属性,结合模板的基本属性生成可视化的HTML 元素。主题是不同tag 结合在一起而形成的。
<input type="text"<#rt/>
name="${parameters.name?default("")?html}"<#rt/>
<#if parameters.get("size")?exists>
size="${parameters.get("size")?html}"<#rt/>
</#if>
<#if parameters.maxlength?exists>
maxlength="${parameters.maxlength?html}"<#rt/>
</#if>
<#if parameters.nameValue?exists>
value="<@s.property value="parameters.nameValue"/>"<#rt/>
</#if>
<#if parameters.disabled?default(false)>
disabled="disabled"<#rt/>
</#if>
<#if parameters.readonly?default(false)>
readonly="readonly"<#rt/>
</#if>
<#if parameters.tabindex?exists>
tabindex="${parameters.tabindex?html}"<#rt/>
</#if>
<#if parameters.id?exists>
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass?exists>
class="${parameters.cssClass?html}"<#rt/>
</#if>
<#if parameters.cssStyle?exists>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
<#if parameters.title?exists>
title="${parameters.title?html}"<#rt/>
</#if>
<#include "/${parameters.templateDir}/simple/scripting-events.ftl" />
<#include "/${parameters.templateDir}/simple/common-attributes.ftl" />
/>
我们考虑标签(Tag )使用模板(Template )生成HTML 的过程,根据不同的模板,坑顶可以生成不同的HTML 画面,这样我们可以把不同tag 的,视觉效果一致的模板放在一起:
例如:
<
s:form
>
TemplateForm_A, TemplateForm_B
<
s:textfield
>
TemplateTextField_A, TemplateTextField_B
<
s:password
>
TemplatePassword_A, TemplatePassword_B
<
s:submit
>
,
TemplateSubmit_A, TemplateSubmit_B
<
s:reset
>
TemplateReset_A, TemplateReset_B
这样将_A 的模板放在一起叫做A 主题(Theme ),将_B 的模板放在一起叫B 主题。这样我们在分别使用A 主题,B 主题的时候可以得到同一个Tag 的不同的视觉效果。
模版和主题的概念处在Struts Tag 的核心位置。
Struts2
默认提供了四种主题:
Simple
主题:最简单的主题
XHTML
主题:默认主题,使用常用的HTML 技巧
CSS XHTML
主题: 使用CSS 实现的XHTML 主题
AJAX
主题:基于XHTML 主题,但是同工了AJAX 功能
相关配置:
在struts.properties 文件中有如下项目:
struts.ui.theme=
xhtml
struts.ui.templateDir=
template
struts.ui.templateSuffix=
ftl
struts.ui.theme
的值表示的是使用哪个主题,可选项位:
xhtml,simple,css_html,ajax
其中
xhtml
为默认值。
struts.ui.templateDir
的值表示模板的存放目录。
struts.ui.templateSuffix
的值表示模板文件明的后缀,因为
Struts2
默认使用
FreeMarker
来编写模板,所以这里我们基本使用
ftl
。
另外也可以使用
vm
(
Velocity
)和
jsp
(
Java Server Page
),但是所有的
Template
和
Theme
要我们自己开发。
关于模板文件的存放目录我们需要详细说明,如上述说明,模板文件的存放位置位
template
,那么系统在那里寻找
template
目录呢,
首先,在
web
应用程序中查找,如果应用程序中存在一个叫做
template
的目录(跟
WEB-INF
目录平级),那么所有的文件从这个目录中取得,具体的路径还要加上主题的名字。
然后,如果在
web
应用程序中没有找到
template
目录,那么
struts2
会在
classpath
中寻找,由于
struts2-core-2.0.9.jar
文件中存在
template
目录,其中内置了四种主题,所以会使用这里变的模板。
例如:
如果我们使用了
ajax
主题,那么会在如下位置超找
<s:textfield>
的主题
应用程序
|
/template/ajax/textfield.ftl
|
classpath
|
/template/ajax/textfield.ftl
|
修改或者扩展模板:
有些时候Struts 提供的模板不一定能够满足我们的需求,这时候我们需要修改或者扩展现有模板。重新做新的模板是不明智的,如果是在需要全新的模板,可以考虑基于simple 扩展。
修改:
根据模板的装载机制,可以考虑将模板从struts2-core-2.0.9.jar 文件中解压缩到web 项目目录,之后修改对应的文件。
包装:
XHTML
提供了一个很好的例子,simple 主题提供了基本的功能,XHTML 将它包括起来,例如:
以下是template/xhtml/xxx.ftl (xxx 表示模板名字)文件内容:
<#include "/${parameters.templateDir}/xhtml/controlheader.ftl" />
<#include "/${parameters.templateDir}/simple/xxx.ftl" />
<#include "/${parameters.templateDir}/xhtml/controlfooter.ftl" />
扩展(extend ):
使用棉线对象的特性可以扩展一个主题,扩展一个主题的时候不需要实现所有的模板,只需要实现需要变化的标签。
扩展需要在目录中新建一个叫做theme.properties 的文件,这个文件只有一行,表明了继承而来的主题的名字,例如:
/template/ajax/theme.properties
文件内容为:
parent = xhtml
4.4
节 AJAX 标签(试验阶段)
Struts2
内置了Dojo 0.4 来提供对Ajax 的支持。
想要使用AJAX 标签需要做到两点:
1
使用Ajax 主题
2
在JSP 画面中使用了head 标签配置Ajax 属性
AJAX
标签主要有:
<s:div>
<s:submit>
<s:a>
<s:tabbedPanel>
<s:autocompleter>
AJAX
标签的一些通用属性:
属性
|
说明
|
类型
|
href
|
请求使用的URL
|
String
|
listenTopic
|
使用逗号分割的一组主题列表,这个列表中的主题会导致这个Tag 自己内容(Div ,Autocompleter )重新装载或者执行一个Action (Anchor ,Submit )
|
String
|
notifyTopic
|
使用逗号分割的一组主题列表,向这个列表中的主题发布一些信息,例如:’data’,’type’,’request’ ,参看每个标签的详细说明
|
String
|
showErrorTransportText
|
设置是否显示错误消息(默认显示)
|
Boolean
|
indicator
|
请求过程中显示的对象,通常位ProgressBar 等
|
String
|
Indicator
<img style="display:none"
src="../../${pageContext.request.contextPath}/images/indicator.gif"
alt="Loading..."/>
Topic
监听一个Topic :
dojo.event.topic.subscribe("/refresh", function(param1, param2) {
//this function will be called everytime "/refresh" is published
});
向一个Topic 发布内容:
dojo.event.topic.publish("/refresh", "foo", "bar");
URL
Href
属性对应的URL 必须使用URL 标签定义,例如:
<s:url id="ajaxTest" value="/AjaxTest.action" />
<s:div theme="ajax" href="%{ajaxTest}">
Initial Content
</s:div>
DIV
标签:
Div
主要用来异步的显示数据, PageLoad 会出发Div 中数据的显示,除非把AutoStart 设置为False 。
另外,Div 的数据显示可以使用Topic 来触发。使用listenTopic 来定义触发器。
例如:
<s:url id="ajaxTest" value="/AjaxTest.action" />
<s:div theme="ajax" href="../../%{ajaxTest}" listenTopics="/refresh0,/refresh1"/>
每次想/refresh0,/refresh1 发布内容的时候,上面代码定义的div 都会刷新。
使用updateFreq 可以让Div 周期性的触发,在autoStart 设置位true 的情况下,可以使用delay 来延迟首次画面加载的出发时间,例如:
<s:url id="ajaxTest" value="/AjaxTest.action" />
<s:div theme="ajax" href="../../%{ajaxTest}" updateFreq="2000" delay="3000"/>
上述代码说明,每隔2 秒该div 触发内容更新一次,但是首次画面加载完成之后3 秒div 出发内容更新。
@todo
其他标签
4.5
节 OGNL
OGNL
是Object Graph Navigation Language 的简称,详细相关的信息可以参考:http://www.ognl.org 。这里我们只涉及Struts2 框架中对OGNL 的基本支持。
OGNL
是一个对象,属性的查询语言。在OGNL 中有一个类型为Map 的Context (称为上下文),在这个上下文中有一个根元素(root ),对根元素的属性的访问可以直接使用属性名字,但是对于其他非根元素属性的访问必须加上特殊符号# 。
在Struts2 中上下文为ActionContext ,根元素位Value Stack (值堆栈,值堆栈代表了一族对象而不是一个对象,其中Action 类的实例也属于值堆栈的一个)。ActionContext 中的内容如下图:
|
|--application
|
|--session
context map---|
|--value stack(root)
|
|--request
|
|--parameters
|
|--attr (searches page, request, session, then application scopes)
|
因为Action 实例被放在Value Stack 中,而Value Stack 又是根元素(root )中的一个,所以对Action 中的属性的访问可以不使用标记# ,而对其他的访问都必须使用# 标记。
引用Action 的属性
<s:property value="postalCode"/>
ActionContext
中的其他非根(root )元素的属性可以按照如下的方式访问:
<s:property value="#session.mySessionPropKey"/> or
<s:property value="#session["mySessionPropKey"]"/> or
<s:property value="#request["mySessionPropKey"]/>
Action
类可以使用ActionContext 中的静态方法来访问ActionContext 。
ActionContext.getContext().getSession().put("mySessionPropKey", mySessionObject);
OGNL
与Collection (Lists ,Maps ,Sets )
生成List 的语法为: {e1,e2,e3}.
<s:select label="label" name="name"
list="{'name1','name2','name3'}" value="%{'name2'}" />
上面的代码生成了一个HTML Select 对象,可选的内容为: name1 ,name2 ,name3 ,默认值为:name2 。
生成Map 的语法为:#{key1:value1,key2:value2}.
<s:select label="label" name="name"
list="#{'foo':'foovalue', 'bar':'barvalue'}" />
上面的代码生成了一个HTML Select 对象,foo 名字表示的内容为:foovalue ,bar 名字表示的内容为:barvalue 。
判断一个对象是否在List 内存在:
<s:if test="'foo' in {'foo','bar'}">
muhahaha
</s:if>
<s:else>
boo
</s:else>
<s:if test="'foo' not in {'foo','bar'}">
muhahaha
</s:if>
<s:else>
boo
</s:else>
取得一个List 的一部分:
? –
所有满足选择逻辑的对象
^ -
第一个满足选择逻辑的对象
$ -
最后一个满足选择逻辑的对象
例如:
person.relatives.{? #this.gender == 'male'}
上述代码取得这个人(person )所有的男性(this.gender==male )的亲戚(relatives)
Lambda
表达式
OGNL
支持简单的Lambda 表达式语法,使用这些语法可以建立简单的lambda 函数。
例如:
Fibonacci:
if n==0 return 0;
elseif n==1 return 1;
else return fib(n-2)+fib(n-1);
fib(0) = 0
fib(1) = 1
fib(11) = 89
OGNL
的Lambda 表达式如何工作呢?
Lambda
表达式必须放在方括号内部,#this 表示表达式的参数。例如:
<s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" />
#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)]
定义了一个Lambda 表达式,
#fib(11)
调用了这个表达式。
所以上述代码的输出为:89
在JSP2.1 中# 被用作了JSP EL (表达式语言)的特殊记好,所以对OGNL 的使用可能导致问题,
一个简单的方法是禁用JSP2.1 的EL 特性,这需要修改web.xml 文件:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>
4.6
节 Tag 语法
代码示例:
表达式
|
含义
|
<p>Username: ${user.username}</p>
|
一个在标准上下文中的JavaBean 对象,可以适用Freemarker ,Velocity,JSTL EL 等(不是OGNL )。
|
<s:textfield name="username"/>
|
在Value Stack 中的一个username 属性。
|
<s:url id="es" action="Hello">
<s:param name="request_locale">
es
</s:param>
</s:url>
<s:a href="%{es}">Espanol</s:a>
|
引用Value Stack 中属性的另外一种方法。
|
<s:property
name="#session.user.username" />
|
Session
中的user 对象的username 属性。
|
<s:select
label="FooBar" name="foo"
list="#{'username':'trillian',
'username':'zaphod'}" />
|
一个简单的静态Map ,和put("username","trillian") 一样
|