一、optiontransferselect
optiontransferselect会生成连个列表选择框,并生成系列的按钮用于控制各选项在两个列表框之间的移动升级等。
<s:form action="option">
<s:optiontransferselect doubleList="{'en1','en2','en3'}" list="{'中文1','中文2','中文3'}"
doubleName="enbook" name="cnbook" addAllToLeftLabel="全部左移" addAllToRightLabel="全部右移"
doubleMultiple="true" selectAllLabel="全部选择" emptyOption="true"
doubleEmptyOption="true" headerKey="cn" headerValue="请选择中文" doubleHeaderKey="en"
doubleHeaderValue="前选择英文"
/>
<s:submit value="提交" οnclick="selectRightBook()"></s:submit>
</s:form>
以上我们就创建了optiontransferselect,但是在创建了它之后,我们还关心一个问题,怎么样在action中取得提交的optiontransferselect数据。这边每个列表框传递到action中时,事实上传递过去的参数值类型是string[]的,因此我们的action代码如下
public class OptionAction extends ActionSupport {
private String[] enbook;
private String[] cnbook;
@Override
public String execute() throws Exception {
for (String string : enbook) {
System.out.println(string);
}
return SUCCESS;
}
public String[] getEnbook() {
return enbook;
}
public void setEnbook(String[] enbook) {
this.enbook = enbook;
}
public String[] getCnbook() {
return cnbook;
}
public void setCnbook(String[] cnbook) {
this.cnbook = cnbook;
}
}
大家以为这样就已经获取到传递过来的值了吧,但是输出到控制端,发现字符串数组为空,这是怎么一回事呢?原来表单提交时,两个列表框中传递过去的参数为空,这是本身这个标签的bug引起的,没有将列表框中的选项选中,我们以为已经选中了,可实际上没有。因此,我们自己要手动编写个script,在点击提交按钮时触发,将列表框值选中。
function selectRightBook(){
var right = document.forms[0].enbook;
for(var i=1;i<right.length;i++)
right[i].selected = true;
}
二、optgroup
该标签用于生成一个下拉列表框的选项组,因此,该标签必须放在<s:select /> 标签中使用,一个下拉框中可以包含多个选项组,因此可以在一个<s:select />中使用多个<s:optgroup />标签
使用optgroup 一样需要指定list,listkey,listvalue等属性
<s:select list="{'a','b','c'}">
<s:optgroup label="性别" list="#{'0':'男','1':'女'}" listKey="key"
listValue="value"
></s:optgroup>
<s:optgroup label="年龄" list="#{'0':'10','1':'15'}" listKey="key"
listValue="value"
></s:optgroup>
</s:select>
三、token
<s:token/> 生成如下的内容:(struts.token.name 标识哪个隐藏域存了 token 值)
<input type="hidden" name="struts.token.name" value="struts.token"/>
<input type="hidden" name="struts.token" value="7GXL55LPSGU19SDC9D3VP54I20XT3BVA"/>
注意自定义的表单域别重名了。它的作用是防止表单重复提交,每次加载页面 struts.token 的值都不一样,如果两次提交时该值一样,则认为是重复提交。此时要启用 TokenInterceptor(token) 拦截器,最好是也启用 TokenSessionStoreInterce
2008-5-17 22:39:21 com.opensymphony.xwork2.interceptor.ParametersInterceptor setParameters
严重: ParametersInterceptor - [setParameters]: Unexpected Exception catched: Error setting expression 'struts.token' with value '[Ljava.lang.String;@1c2e163'
2008-5-17 22:39:21 com.opensymphony.xwork2.interceptor.ParametersInterceptor setParameters
严重: ParametersInterceptor - [setParameters]: Unexpected Exception catched: Error setting expression 'struts.token.name' with value '[Ljava.lang.String;@abaf8c'
但不影响使用。不过如果只有 token-session 拦截器却是不行的。
token 和 token-session 拦截器的启用,是在 struts.xml 配置文件中,既可以为包启用,也可以单独为某个 action 启用:
1) 为包启用 token 和 token-session
<package name="TestStruts" extends="struts-default">
<interceptors>
<interceptor-stack name="myStack">
<interceptor-ref name="token" />
<interceptor-ref name="tokenSession" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack" />
<action name="Login" class="com.unmi.struts2.action.LoginAction">
<result name="input">/login.jsp</result>
<result name="invalid.token">/exception.jsp</result>
</action>
</package>
2) 为 Action 启用 token 和 tokenSession
<action name="Login" class="com.unmi.struts2.action.LoginAction">
<interceptor-ref name="token" />
<interceptor-ref name="tokenSession" />
<interceptor-ref name="defaultStack" />
<result name="input">/login.jsp</result>
<result name="invalid.token">/exception.jsp</result>
</action>
注意
1.token、tokenSession 和 defaultStack 的顺序要保证,
2.还需要加上名为 "invalid.token" 的 result,当发现重复提交时转向到这个逻辑页,/exception.jsp,
3.在 /exception.jsp 加上 <s:actionerror />在出现重复提交时就会提示:
注意自定义的表单域别重名了。它的作用是防止表单重复提交,每次加载页面 struts.token 的值都不一样,如果两次提交时该值一样,则认为是重复提交。此时要启用 TokenInterceptor(token) 拦截器,最好是也启用 TokenSessionStoreInterce
4.defaultStack是系统默认的拦截器栈,之前没配置它,实际上该拦截器默认是生效的,所以不用配置。此处因为显示使用了token拦截器,所以必须显示配置使用defaultStack拦截器,否则它不会默认生效。另外,如果表单页没有token标签,千万不要使用token拦截器,否则它将导致无法提交表单