Struts 2为大家提供了不少常用的很酷的表单标志,简化了我们程序员的工作。不过,由于这些都是新标志,大家可能在使用上还存在不少疑问。本文将就朋友们的回复、留言或Email上的问题,分别对这些酷标志进行讲述。
表单标志使用小技巧
Struts 2的表单标志在输出(render)HTML时,使用了模板的概念,增加了复杂性(因为它不像Struts 1.x的表单标志,它通常都是一个标志对应HTML的一个元素),因此大家在使用时,需要一些技巧:
- Struts 2的UI标志的表单标志默认是以表格布局,按钮是右对齐的。如果你不喜欢此风格,你可以简单地将<s:form />标志的“theme”属性设为“simple”,然后用以往的做法自已布局表单元素(注意:此法有利有弊,弊就是当你将“theme”属性设为“simple”时,表单标志以最简单方式输出HTML,所以你可能失去一些默认输出提供的便利,如:友好的错误信息的显示,或客户端的表单验证等)。当然更好的做法是通过CSS或自定义主题(theme)然后应用到整个应用程序,这样可以获得一致的页面风格,加强用户体验(我会在以后的文章对此进行讲解);
- 当你在页面上加入某些标志(如:<s:doubleselect />等)时,应该通过action来访问页面,而不是通过*.jsp的URL直接访问。
下面我将分别对这些标志进行讲述:
1、<s:checkboxlist />
大家对<s:checkboxlist />的最大的疑问可能是:“如何在默认情况下,选中某些checkbox?”
答案其实很简单,只需要将其“value”属性设为你的要选中的值,如以代码所示:
<% @ taglib prefix = " s " uri = " /struts-tags " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< title > Struts 2 Cool Tags - < s:checkboxlist/ > </ title >
< s:head />
</ head >
< body >
< h2 > < s:checkboxlist/ > </ h2 >
< s:form action ="Store" >
< s:checkboxlist name ="skills1"
label ="Skills 1"
list ="{ 'Java', '.Net', 'RoR', 'PHP' }"
value ="{ 'Java', '.Net' }" />
< s:checkboxlist name ="skills2"
label ="Skills 2"
list ="#{ 1:'Java', 2: '.Net', 3: 'RoR', 4: 'PHP' }"
listKey ="key"
listValue ="value"
value ="{ 1, 2, 3 }" />
</ s:form >
</ body >
</ html >
分布运行应用程序,在浏览器中键入:http://localhost:8080/Struts2_CoolTags/checkboxlist.jsp,出现如下图所示页面:
2、<s:doubleselect />
大家看Struts 2的showcase的例子,<s:doubleselect />的用法如下所示:
tooltip ="Choose Your State"
label ="State"
name ="region" list ="{'North', 'South'}"
value ="'South'"
doubleValue ="'Florida'"
doubleList ="top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}"
doubleName ="state"
headerKey ="-1"
headerValue ="---------- Please Select ----------"
emptyOption ="true" />
很多朋友问:“上面的‘list’属性只有两个值,如果我有三个或更多的值,‘doublelist’属性应该如何设定呢?”
我建议的做法是先定义一个Map类型的对象,键为“list”的集合,值则为“doubleList”的集合,然后“doubleList”的OGNL写成“#myMap[top]”,如以下代码所示:
<% @ taglib prefix = " s " uri = " /struts-tags " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< title > Struts 2 Cool Tags - < s:doubeselect/ > </ title >
< s:head />
</ head >
< body >
< h2 > < s:doubleselect/ > </ h2 >
< s:form action ="Store" >
< s:set name ="foobar"
value ="#{'Java': {'Spring', 'Hibernate', 'Struts 2'}, '.Net': {'Linq', ' ASP.NET 2.0'}, 'Database': {'Oracle', 'SQL Server', 'DB2', 'MySQL'}}" />
< s:doubleselect list ="#foobar.keySet()"
doubleName ="technology"
doubleList ="#foobar[top]"
label ="Technology" />
</ s:form >
</ body >
</ html >
分布运行应用程序,在浏览器中键入:http://localhost:8080/Struts2_CoolTags/doubleselect.action,出现如下图所示页面:
3、<s: token />
这个标志可能大家不常用,不过本人认为它还是挺有用的。在使用Struts 1.x时,因为跳转通常是用Forward(而不是Redirect)实现的,所以当用户完成请求后,按“F5”刷新页面时,就会重新提交上次的请求,这样经常会出错。要解决这个问题,<s:token />可以帮你忙。
实现原理
在页面加载时,<s: token />产生一个GUID(Globally Unique Identifier,全局唯一标识符)值的隐藏输入框如:
< input type ="hidden" name ="struts.token" value ="BXPNNDG6BB11ZXHPI4E106CZ5K7VNMHR" />
同时,将GUID放到会话(session)中;在执行action之前,“token”拦截器将会话token与请求token比较,如果两者相同,则将会话中的token删除并往下执行,否则向actionErrors加入错误信息。如此一来,如果用户通过某种手段提交了两次相同的请求,两个token就会不同。
具体实现
首先看一下Action的代码:































以上代码一目了然,再看看JSP的写法:
<% @ taglib prefix = " s " uri = " /struts-tags " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< title > Struts 2 Cool Tags - < s:token/ > </ title >
< s:head />
</ head >
< body >
< h2 > < s:token/ > </ h2 >
< s:actionerror />
< s:form action ="Token" >
< s:textfield name ="message" label ="Message" />
< s:token />
< s:submit />
</ s:form >
</ body >
</ html >
JSP也很简单,就是加入<s:token />标志。接下来是Actoin配置的XML片段:
<! DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
< package name ="Struts2_COOL_TAGS_DEMO" extends ="struts-default" >
< action name ="Token" class ="tutorial.CoolTagAction" >
< interceptor-ref name ="defaultStack" />
< interceptor-ref name ="token" />
< result name ="invalid.token" > /token.jsp </ result >
< result > /token.jsp </ result >
</ action >
< action name ="*" >
< result > /{1}.jsp </ result >
</ action >
</ package >
</ struts >
以上XML片段值注意的是加入了“token”拦截器和“invalid.token”结果,因为“token”拦截器在会话token与请求token不一致时,将会直接返回“invalid.token”结果。
发布运行应用程序,在浏览器中键入:http://localhost:8080/Struts2_CoolTags/token.jsp,出现如下图所示页面:
随便填点东西并提交页面,一切正常返回以上页面,然后按“F5”刷新页面,在弹出的对话框中点击“Retry”,出现如下图所示页面:
4、<s:datetimepicker />、<s:optiontransferselect />和<s:updownselect />
这几个标志的使用相对简单,所以我想小举一例即可,以下是JSP的代码:
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< title > Struts 2 Cool Tags - Others </ title >
< s:head />
</ head >
< body >
< h2 > Others </ h2 >
< s:form action ="Store" >
< s:datetimepicker name ="birthday" label ="Birthday" />
< s:updownselect
label = "Favourite Countries"
list ="#{'england':'England', 'america':'America', 'germany':'Germany'}"
name ="prioritisedFavouriteCountries"
headerKey ="-1"
headerValue ="--- Please Order Them Accordingly ---"
emptyOption ="true" />
< s:optiontransferselect
label ="Favourite Cartoons Characters"
name ="leftSideCartoonCharacters"
leftTitle ="Left Title"
rightTitle ="Right Title"
list ="{'Popeye', 'He-Man', 'Spiderman'}"
multiple ="true"
headerKey ="headerKey"
headerValue ="--- Please Select ---"
emptyOption ="true"
doubleList ="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
doubleName ="rightSideCartoonCharacters"
doubleHeaderKey ="doubleHeaderKey"
doubleHeaderValue ="--- Please Select ---"
doubleEmptyOption ="true"
doubleMultiple ="true" />
</ s:form >
</ body >
</ html >
发布运行应用程序,在浏览器中键入:http://localhost:8080/Struts2_CoolTags/others.jsp,出现如下图所示页面:
总结
Struts 2在标志上的确比Struts 1.x丰富了许多,同时模板机制也给程序员带来不少方便(如果你不太喜欢个性化的风格)。另外,Struts 2还有一些AJAX(如<s: autocompleter />等)的标志和非表单的UI标志(如<s: tree />等),我会在以后的文章中讲述其使用。