论坛首页 Java版 Webwork

在WebWork2 Action中如何自动设置Array、List、Map

浏览 20157 次
该帖已经被评为精华帖
作者 正文
时间:2004-11-10
大家知道,WebWork使用拦截器可以自动将request的paramter设置Action的属性中,这样减少很多设置值的繁杂。如果Action的属性是一个单独的对象,则通过表达式语言(OGNL)可以轻松存取整个对象结构,简单说,其实它也就是调用Bean的get、set方法。例如:mockData.name,这个表达式,其实就是在调用MockData类的getName()或setName()方法。
但,如果我们的属性是一个集合,那又该如何处理?
例如:我们的AggregateAction,它的一个数组属性如下:
[code:1]
private Object[] arrayData = new Object[4];
public Object[] getArrayData(){
return arrayData;
}
[/code:1]
对这样的数组,我们Jsp页面对应的表达式则为:arrayData[0]、arrayData[1]等
其中[0]、[1]就代表了数组的索引。我们的Input标签就可以这样:
[code:1]
<input name="arrayData[0]" value="arrayData_0">
<input name="arrayData[1]" value="arrayData_1">
[/code:1]
使用数组作为属性时,注意数组的长度必须事先确定,不可以动态改动数组的大小。
这时,你想到的一定是List。既然是List,你一定又会疑问如何运行时得知List元素的类型,自动进行类型转换?
XWork为我们提供了XWorkList,它继承了ArrayList类,在它的构造函数中传入该List元素的类型(当然,你也可以通过自己定义的类型转换来实现)。
例如:
private List listData = new XWorkList(MockData.class);

我们页面中的input就可以如下:
[code:1]
<input name="listData[0].name" value="listData_0">
<input name="listData[1].name" value="listData_1">
[/code:1]

剩下的事情就有框架来帮你处理。
对Map,原理同List一样,XWork提供了XWorkMap,它的构造函数也要传入Value元素的类型。
例如:
private Map mapData = new XWorkMap(MockData.class);但要注意的是:它的设置表达式为mapData['key'].name,其中“key”就是Map中的key,它必须放入“''”中。

顺便说一句,WebWork会自动处理null的情况。例如
private MockData nullData = null;
当你调用
[code:1]
<ww:property value="nullData.name"/>
[/code:1]
虽然nullData为null,但WebWork会自动为你创建新的MockData实例,避免了烦人的NullPointerException问题。
   
时间:2004-11-10
完整代码如下:
//AggregateAction.java
[code:1]
import java.util.List;
import java.util.Map;

import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.util.XWorkList;
import com.opensymphony.xwork.util.XWorkMap;

/**
* @author moxie
* achqian@yahoo.con.cn
*/
public class AggregateAction implements Action{
private MockData nullData = null;

private List listData = new XWorkList(MockData.class);

private Object[] arrayData = new Object[4];

private Map mapData = new XWorkMap(MockData.class);

public String doDefault() throws Exception{
return INPUT;
}

/* (non-Javadoc)
* @see com.opensymphony.xwork.Action#execute()
*/
public String execute() throws Exception {
return SUCCESS;
}

public Object[] getArrayData(){
return arrayData;
}

public List getListData(){
return listData;
}

public Map getMapData(){
return mapData;
}

public MockData getNullData(){
return nullData;
}
}
[/code:1]

//MockData .java
[code:1]
/**
* @author moxie
* achqian@yahoo.con.cn
*/
public class MockData {
private String name;
public MockData() {

}

/**
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}
public String toString(){
return "name = "+name;
}
}
[/code:1]

//aggregate.jsp
[code:1]
<html>
<head>
<title>First WebWork Example</title>
</head>
<body>

<form name="form1" action="<%=request.getContextPath()%>/aggregate/testAggregate.action" method="POST">
<input name="listData[0].name" value="listData_0"><p>
<input name="listData[1].name" value="listData_1"><p>
<input name="listData[2].name" value="listData_2"><p>

<input name="arrayData[0]" value="arrayData_0"><p>
<input name="arrayData[1]" value="arrayData_1"><p>
<input name="arrayData[2]" value="arrayData_2"><p>

<input name="mapData['0'].name" value="mapData_0"><p>
<input name="mapData['1'].name" value="mapData_1"><p>
<input name="mapData['2'].name" value="mapData_2"><p>

<input type="submit" name="Submit"><br>
</form>
</body>
</html>
[/code:1]

//aggregate-result.jsp

[code:1]
<%@taglib uri="webwork" prefix="ww"%>
<html>
<head>
<title>First WebWork Example</title>
</head>
<body>
测试List:
<ww:iterator value="listData">
<ww:property/><br>
</ww:iterator>
<p>

测试数组:
<ww:iterator id="arrayD" value="arrayData">
<ww:property/><br>
</ww:iterator>
<p>

测试Map:
<ww:iterator id="mapD" value="mapData">
<ww:property/><br>
</ww:iterator>
<p>

取Map中的数据:
<ww:property value="mapData['0'].name"/><br>
<p>

测试Null对象:
<ww:property value="nullData.name"/><br>

</body>
</html>
[/code:1]
   
0 请登录后投票
时间:2004-11-10
我不明白的是,用数组有什么不好的呢,方便的很,为什么要弄那么麻烦呢?

<input name="arrayData" value="arrayData_0"><p>
<input name="arrayData" value="arrayData_1"><p>
<input name="arrayData" value="arrayData_2"><p>


页面如上,输入框的name都用一个名字,Action相应的定义一个对应类型的数组,例如:

private String[] arrayDate;
...setter/getter...

Webwork会自动定义相应长度的数组,填充数组,这样不是很简洁吗?
   
0 请登录后投票
时间:2004-11-11
客户端,界面上的引用....比如在一个webgrid里面,有时候需要进行客户端计算,因此每个object有不同名字。
   
0 请登录后投票
时间:2004-11-11
robbin 写道

private String[] arrayDate;
...setter/getter...

Webwork会自动定义相应长度的数组,填充数组,这样不是很简洁吗?


这样确实可以,很方便。但如果是
[code:1]
private MockData[] mockArray;
public MockData[] getMockArray(){
return mockArray;
}
public void setMockArray(MockData[] mockArray){
this.mockArray = mockArray;
}
[/code:1]
页面
[code:1]
<input name="mockArray.name" value="mockArrayData_1"><p>
<input name="mockArray.name" value="mockArrayData_2"><p>
[/code:1]
则有下面的错误
[code:1]
严重: Could not create and/or set value back on to object
java.lang.InstantiationException: [Lexample.array.MockData;
at java.lang.Class.newInstance0(Class.java:293)
at java.lang.Class.newInstance(Class.java:261)
at com.opensymphony.xwork.ObjectFactory.buildBean(ObjectFactory.java:86)
at com.opensymphony.xwork.util.InstantiatingNullHandler.createObject(InstantiatingNullHandler.java:115)
at com.opensymphony.xwork.util.InstantiatingNullHandler.nullPropertyValue(InstantiatingNullHandler.java:80)
[/code:1]

再说,假如我的MockData对象有2个属性id,name。如果界面上有2个MockData对象,你又怎么表示?
[code:1]
<input name="mockData.name" value="mockData_1"><p>
<input name="mockData.name" value="mockData_2"><p>

<input name="mockData.id" value="11"><p>
<input name="mockData.id" value="22"><p>
[/code:1]
这样你必须事先确定数组元素的位置!
   
0 请登录后投票
时间:2004-11-12
我在实地作项目的时候让程序员自己搞这些是很麻烦的事情,所以直接用Map就可以,在底层封住好
   
0 请登录后投票
时间:2004-12-06
那么如何来处理list中每个元素是个对象数组的情况呢?

比如:
[code:1]List result = new ArrayList();
Object[] item1=new Object[]{StringObject,HelloObject,ForumObject};
Object[] item2=new Object[]{StringObject,HelloObject,ForumObject};
Object[] item3=new Object[]{StringObject,HelloObject,ForumObject};
result.add(item1);
result.add(item2);
result.add(item3);[/code:1]
如何在jsp的ognl访问每个list元素的ForumObject.name属性呢》?
   
0 请登录后投票
时间:2004-12-06
试试看:
result[0][0] => item1的stringObject
result[0][1] => item1的helloObject
...
result[2][2].name => item3的ForumObject.name
   
0 请登录后投票
时间:2004-12-06
谢谢 readOnly

确实可以,还想请教,
对于
[quote]result[0][0] => item1的stringObject
result[0][1] => item1的helloObject
...
result[2][2].name => item3的ForumObject.name[/quote]
能否使用变量来遍历
例如result[i][j]的方式

[/quote]
   
0 请登录后投票
时间:2004-12-06
不熟悉iterator tag, 不知道怎么写, 不过它肯定支持N重的遍历, 查一下文档:
http://wiki.opensymphony.com/display/WW/Iteration+Tags

里面有一个先遍历group, 然后再遍历user的例子.
   
0 请登录后投票
论坛首页 Java版 Webwork

跳转论坛: