论坛首页 Java版 Webwork

webwork 2.2 中如何给Collection赋值

浏览 11881 次
该帖已经被评为精华帖
作者 正文
最后更新时间:2006-01-05
原本javaeye有这么一篇帖子“在WebWork2 Action中如何自动设置Array、List、Map”,是moxie大哥写的。
http://forum.javaeye.com/viewtopic.php?t=8770

但是已经是2004年11月的文章了,在webwork 2.2 b4中,XWorkList和XWorkMap已经是deprecated状态了,当时我就一头雾水,也没找到什么好的线索。
去java.net下载了XWork的最新代码,看到了其中的注释,说这个工作已经可以自动完成了。
又几经周折,才算搞明白先在如何让List、Map等工作起来,给予2.2 b4和b5工作正常:

下面简单介绍一下:
1、如果要将值映射到pojo的collection,则需要使用conversion功能。
如我又一个Action,叫testAction:
[code:1]public class testAction extends ActionSupport {
private Collection smoeAttrs = null;//(使用webwork自动负值,应有对应getter和setter)
private IDeptJgzTjkEcoAttDAO ecoAttDAO = null;//(改DAO使用Spring注入,应有相应setter)

    public String execute() throws Exception {
        if (log.isDebugEnabled()) {
log.debug("performing execute() method!");
        }

//持久化collection里面的pojo
for (Iterator iterator = smoeAttrs.iterator(); iterator.hasNext();) {
            SomeAttr someAttr = (SomeAttr) iterator.next();
            ecoAttDAO.saveOrUpdate(someAttr, someAttr.getId());
        }

       return Action.SUCCESS;
    }
}[/code:1]
对应一个pojo:
[code:1]package org.tin.test;

public class SomeAttr implements Serializable {

/** The composite primary key value. */
private java.lang.Long id;

private java.lang.Float fild1;
private java.lang.String fild2;
private java.util.Date fild3;

/*
....
对应的getter和setter
*/
}[/code:1]
可以看到,上面的Action声明的时候没有任何涉及到XWorkList的地方(moxie介绍的那种风格),也就是说现在webwork并不知道Collection里面放的pojo的类型。这就是Webwork目前的高明之处,这样的代码非常干净。但是如果要自动设定Collection的值,访问到这些Pojo,则一定要知道Pojo的类型,Webwork如何做呢?
通过-conversion配置。
需要在对应该才那个testAction.java的相同目录写一个testAction-conversion.properties文件(格式就是Action名字+“-conversion.properties”)。
文件里面注明:
Element_someAttrs = org.tin.test.SomeAttr (以前版本曾经用过Collection、Map分开,但是现在不管什么类型,都用Element)
格式就是“Element_”+Action中Collection的名字+“=”+你的pojo的完整类名

如此配置后,自动设置值的时候就可以知道你的pojo的类型了,很干净。

下面一小段由于我接触Webwork不久,所以是个很初级的经验,如果需要则自取:
回忆moxie帖子中的重要的部分,在post到相应action的页面的form中,input要遵循这样的命名:
对应刚才所说的那个pojo:
[code:1]<form>
<input  name="someAttrs[0].fild1" value="45555.6" id="xxx11" />
<input  name="someAttrs[0].fild2" value="test" id="xxx12" />
<input  name="someAttrs[0].fild3" value="2006-01-05" id="xxx13" />
<input  name="someAttrs[1].fild1" value="45555.6" id="xxx21" />
<input  name="someAttrs[1].fild2" value="test" id="xxx22" />
<input  name="someAttrs[1].fild3" value="2006-01-05" id="xxx23" />
<input  name="someAttrs[2].fild1" value="45555.6" id="xxx31" />
<input  name="someAttrs[2].fild2" value="test" id="xxx32" />
<input  name="someAttrs[2].fild3" value="2006-01-05" id="xxx33" />
</form>[/code:1]
如何输出?很简单,在列表页中:
[code:1]<ww:iterator value="someAttrs" status="someAttrsIter">
<tr>
<td>
<ww:hidden name="someAttrs[%{#someAttrsIter.index}].id" value="%{id}"/>
<ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild1" value="%{fild1}"/></td>
<td><ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild2 value="%{fild2}"/></td>
<td><ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild3" value="%{fild3}"/></td>
</tr>
</ww:iterator>[/code:1]即可以,因为iteratror这个tag支持iteratroStatus这个东西,用它可以获取index、isOdd等信息,很方便。

配合
[code:1]<action name="saveAction" class="testAction">
<result name="success" type="redirect">/loadByInf.action?id=${someAttrOwner.id}</result>
</action>[/code:1]则很容易的实现对Collection的CRUD。正好用到了ONGL的集中基本访问方式:#、%{}、${}

以上内容,错漏难免。因为今天终于可以偷闲,赶紧结绳记之。欢迎大家讨论更简便的方法。
   
最后更新时间:2006-01-05
我觉得XWorkList, XWorkMap还是很有用的,挺好的设计,其实没有必要deprecated。像现在的做法也还是有不足之处,只支持第一级Collection,对多层次好像还是要用老的办法,或者说也可以我还没看到。

我多数使用ModelDriven,一般就是一个model操作,用到Collection的地方那就是第二层之后了,还是得用XWorkList,model不是简单的new出来的,而是是用工厂产生XWork化的model,例如。

[code:1]public class UserXWorkFactory {
    public static User getInstance() {
        User user = new User();
        user.setEmails(new XWorkList(UserEmail.class));
        return user;
    }
}[/code:1]

这样用起来就比较方便了。
------
补充:原来对converter的理解有误,现在看来上面的代码多此一举了
   
0 请登录后投票
最后更新时间:2006-03-06
xfv5k 写道
楼主,我按你这个贴子搞半天也没成功.
按你设计的那个表单,提交后,action得不到值.报错如下:
java.lang.IllegalArgumentException: attempt to create saveOrUpdate event with null entity


楼主你能不能搞好了,传个实例上来,方便学习.


这个。问题应该不出在conversion的部分吧,可能你的代码有问题。很多朋友都搞定啦,现在Webwork wiki介绍的也满详尽。除了给Action设置conversion,还可以给pojo设置conversion呢。
http://www.blogjava.net/iamtin/archive/2006/02/16/31099.html

你可以把你的代码法上来,我们帮你看看问题出在哪里。null应该是ognl没有正确赋值,你可以打开debug看看问题出在哪里。
   
0 请登录后投票
最后更新时间:2006-03-10
你用的Webwork什么版本?是2.2 or 2.2.1?
还有你后面的页面有一个freemarker一个jsp版本是啥意思?没有xwork不知道你的action的流程呀。如果freemarker那个是post的页面的话我觉得你可以把它实际渲染后的html文件的源码贴过来,那样就可以判断问题出在哪里了(是输出格式有错,还是post后ognl set有错)。
你可以把log4j的com.opensymphony=debug,这样跟踪一下ognl报错内容呀。
   
0 请登录后投票
最后更新时间:2006-03-29
问题应该出在你的ftl模版里面。你的模版中ww:property 只有name属性,而里面又写的是users[0]这样的形式。property默认value取name相同的值,但你写成users[0]形式后就需要指定value值了。返回的list里面的值就为null。
估计如此。
   
0 请登录后投票
最后更新时间:2006-04-04
xfv5k 写道
Tin 写道
问题应该出在你的ftl模版里面。你的模版中ww:property 只有name属性,而里面又写的是users[0]这样的形式。property默认value取name相同的值,但你写成users[0]形式后就需要指定value值了。返回的list里面的值就为null。
估计如此。 :roll:


我搞成了,但不是根据你说的那个方法。
参考了这个贴子,http://forum.javaeye.com/viewtopic.php?t=15709

webwork2.2.2自带例子showcase 的PersonManager Sample 是最好的例子。


我又下载了你新的dztc.rar那个包,看了半天,没明白你怎么解决了问题,也不知道你原先问题出在哪里,我倒是一头雾水。

这段代码什么意思?
[code:1]public class TestAction extends ActionSupport{
private List users=new ArrayList();
private User user;
public TestAction(){
for(int i=0;i<2;i++)
users.add(new User());
}
public void setUsers(List users){
this.users=users;
}
public List getUsers(){
return users;
}
public String execute(){
/*
for(Iterator it=users.iterator();it.hasNext();){
user=(User)it.next();
users.add(user);
}
*/
return SUCCESS;
}

}[/code:1]

你不是根本就没从页面读取数据么?

希望你把解决问题的细节写一写,对大家都很有帮助。:D
   
0 请登录后投票
最后更新时间:2006-04-04
建议xfv5k遇到null的问题调试就好了,看看是不是传进来的时候就是空的还是后面哪个地方搞错了,从parameterInterecpter一直跟到hibernate里面肯定能找到原因。
   
0 请登录后投票
最后更新时间:2006-04-05
我调整了一下xfv5k的代码,使之可以在webwork的quickstart 里直接运行。
解压到webwork 的webapp目录下。
然后用
%java_home%\bin\java -jar webwork-2.2.2.jar quickstart:dztc
即可执行。
   
0 请登录后投票
最后更新时间:2006-04-05
xfv5k 写道
Tin 写道


TIN我那个包解压后,lib目录下加载必要的包(如:webwork2.2任何一个例子lib目录下的包都可以。),就可以布署成功。然后访问http://localhost:8080/dztc/tmd/add!input.action就可以感受到了。我觉得你没有试一下我提供的例子。

没什么细节,我也搞不懂,这个贴子说得比我明白http://forum.javaeye.com/viewtopic.php?t=15709


我算明白了。其实本意这个conversion是为了给Collection赋值。而你的问题是录入的界面load时出错,而不是post出错。其实这样的代码还是相当不好的。
可以重构到prepare()方法,使用prepareInteceptor。
还有,新的xwork-tiger已经支持泛型Collection,就不用写conversion文件了,很方便自己写scaffold,可以把玩一下。
   
0 请登录后投票
最后更新时间:2006-04-05
建议尽量把发布的例子做成quickstart模式的。
(如果想保持不一样的目录结构,编个好点的xml配置)

我刚改了可以用jettyplus支持jndi的了 。
:)

打算以后不用tomcat调试,直接拿quickstart调试了。
   
0 请登录后投票
论坛首页 Java版 Webwork

跳转论坛:
JavaEye推荐