论坛首页 Java企业应用论坛

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

浏览 34796 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-11-10  
大家知道,WebWork使用拦截器可以自动将request的paramter设置Action的属性中,这样减少很多设置值的繁杂。如果Action的属性是一个单独的对象,则通过表达式语言(OGNL)可以轻松存取整个对象结构,简单说,其实它也就是调用Bean的get、set方法。例如:mockData.name,这个表达式,其实就是在调用MockData类的getName()或setName()方法。
    但,如果我们的属性是一个集合,那又该如何处理?
例如:我们的AggregateAction,它的一个数组属性如下:
private Object[] arrayData = new Object[4];
public Object[] getArrayData();{
	return arrayData;
}

对这样的数组,我们Jsp页面对应的表达式则为:arrayData[0]、arrayData[1]等
其中[0]、[1]就代表了数组的索引。我们的Input标签就可以这样:
<input name="arrayData[0]" value="arrayData_0">
<input name="arrayData[1]" value="arrayData_1">

使用数组作为属性时,注意数组的长度必须事先确定,不可以动态改动数组的大小。
    这时,你想到的一定是List。既然是List,你一定又会疑问如何运行时得知List元素的类型,自动进行类型转换?
    XWork为我们提供了XWorkList,它继承了ArrayList类,在它的构造函数中传入该List元素的类型(当然,你也可以通过自己定义的类型转换来实现)。
例如:
private List listData = new XWorkList(MockData.class);

我们页面中的input就可以如下:
<input name="listData[0].name" value="listData_0">
<input name="listData[1].name" value="listData_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;
    当你调用
<ww:property value="nullData.name"/>

    虽然nullData为null,但WebWork会自动为你创建新的MockData实例,避免了烦人的NullPointerException问题。
   发表时间:2004-11-10  
完整代码如下:
//AggregateAction.java
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;
	}
}


//MockData .java
/**
 * @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;
	}
}


//aggregate.jsp
<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>


//aggregate-result.jsp

<%@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>
0 请登录后投票
   发表时间:2004-11-10  
我不明白的是,用数组有什么不好的呢,方便的很,为什么要弄那么麻烦呢?

&lt;input name="arrayData" value="arrayData_0"&gt;&lt;p&gt;
&lt;input name="arrayData" value="arrayData_1"&gt;&lt;p&gt;
&lt;input name="arrayData" value="arrayData_2"&gt;&lt;p&gt;


页面如上,输入框的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会自动定义相应长度的数组,填充数组,这样不是很简洁吗?


这样确实可以,很方便。但如果是
private MockData[] mockArray;
public MockData[] getMockArray();{
         return mockArray;
}
public void setMockArray(MockData[] mockArray);{
          this.mockArray = mockArray;
}

页面
<input name="mockArray.name" value="mockArrayData_1"><p>
<input name="mockArray.name" value="mockArrayData_2"><p>

则有下面的错误
严重: 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);


再说,假如我的MockData对象有2个属性id,name。如果界面上有2个MockData对象,你又怎么表示?
<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>

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

比如:
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);;

如何在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

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

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

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

跳转论坛:
Global site tag (gtag.js) - Google Analytics