Struts2中使用标签的问题

时间:2022-01-27 19:41:19

备注:Struts1中出现的类似checkbox问题可以通过ActionForm的reset方法解决。


(版本为struts-2.1.7)

问题: 用户没有选中任何checkbox时,提交不生效。
原因: load和edit操作共用同一个Action类的prepare()方法; params interceptor对checkbox处理方式比较特殊。



使用标签<s:checkboxlist>时,如果页面上所有的checkbox都没被选中,Struts2的parameter interceptor不会对相应属性赋值,从而造成程序bug。例如,

页面timeframe.page:
<s:form id="tform" method="post" action="edit">

<s:checkboxlist id="seltimeframes" name="seltimeframes" key="lbl.timeframe" list="timeframeList" listKey="id" listValue="name" />

</s:form>


正常情况下,如果使用defaultStack,调用interceptors的先后顺序是先prepare,然后modelDriven,最后params。如果使用paramsPrepareParamsStack,则在调用prepare之前要先调用一次params,将输入参数传给prepare()使用。但是问题是: 如果没有任何checkbox被勾选,params根本不给seltimeframes属性赋值

产生问题的具体场景(scenario)是这样的:
在装载(load)页面timeframe.page的时候,需要通过prepare()方法给seltimeframes属性设置初始值:
public void prepare() {
   ....
   seltimeframes.add(...);
}

然后用户将所有的checkboxes取消勾选,在提交表单调用edit这个action的时候(load和edit操作共用同一个Action类), 由于struts2 interceptor stack仍然会调用prepare()方法,但是在执行edit时我们不希望seltimeframes.add(...);这条语句生效。在正常的情况下, 我们希望params这个interceptor能将属性seltimeframes重新设置为用户提交的值,即seltimeframes为空,从而覆盖prepare()中的设置。但是在没有任何checkbox被选中的情况下,params interceptor并没这样做。从而edit操作得到的结果仍然是用户取消勾选之前的状态,出现bug!

如果要改正过来,有一个做法是在调用seltimeframes.add(...);这条语句时判断是load操作还是edit操作的prepare(),因此可以在<s:form>中加一个hidden属性:
<s:form id="tform" method="post" action="edit">

<s:hidden id="submitflag" name="submitflag" value="1"/>
<s:checkboxlist id="seltimeframes" name="seltimeframes" key="lbl.timeframe" list="timeframeList" listKey="id" listValue="textName" />

</s:form>

然后将edit的action改为:
@Component
@Scope("prototype")
@InterceptorRefs({
    @InterceptorRef(value="paramsPrepareParamsStack")
})
public class EditAction implements Preparable,ModelDriven<Item>{
    private List<Integer> seltimeframes = new ArrayList<Integer>();
    private Integer submitflag;
    public void prepare() {
       ....
       if(submitflag == null || submitflag.intValue() != 1){    
          seltimeframes.add(...);
       }
    }    
    ....
}

这样保证了用户提交的数据能够生效。