有一个对象ObjectA
,其中包含ObjectB
列表。 TreeMap
内有一个ObjectB
。此TreeMap
有一个String
作为键,另一个List
的{{1}}作为值。 ObjectC
内部TreeMap
和list
已使用jsp
和s:iterator
显示在s:textfield
上,并且正确显示。即s:textfield中的“值”是正确的。现在,修改文本字段时出现问题。我们如何捕获动作类中ObjectC内的修改值?使用此处给出的代码,键(“Key1”)出现在操作中,但值为null。
Java代码
public class ObjectA implements Serializable {
private Integer attr1;
private List<ObjectB> objB;
//...getters and setters....
public class ObjectB implements Serializable {
private Integer attr11;
private TreeMap<String,List<ObjectC>> allPlainFields;
// ...getters and setters....
public class ObjectC implements Serializable {
private Integer attr111;
public String attr112;
// ...getters and setters....
JSP代码
<s:iterator value="objA.objB" var="currentObjB" status="currentGroupStatus">
<s:iterator value="#currentObjB.allPlainFields" var="parentMap" status="headerStatus">
<s:iterator value="#parentMap.value" var="fieldList" status="fieldStatus">
<s:textfield name="objA.objB[%{#currentGroupStatus.index}].allPlainFields['%{#parentMap.key}'][%{#fieldStatus.index}].attr112"/>
</s:iterator>
</s:iterator>
HTML呈现:
<input type="text" id="review-act1_objA_objB_0__allPlainFields_'Key1'__6__attr112" value="Correct Value" name="objA.objB[0].allPlainFields['Key1'][0].attr112">
eclipse的“VAriables”视图中的对象结构显示:
objA Object A (id=955)
objB ArrayList<E> (id=966)
elementData Object[10] (id=967)
[0] ObjectB (id=968)
allPlainFields TreeMap<K,V> (id=972)
comparator null
descendingMap null
entrySet TreeMap$EntrySet (id=979)
keySet null
modCount 1
navigableKeySet null
root TreeMap$Entry<K,V> (id=980)
size 1
values null
[1] ObjectB (id=969)
[2] ObjectB (id=970)
[3] ObjectB (id=971)
[4] null
[5] null
[6] null
[7] null
[8] null
[9] null
modCount 4
size 4
****在Eclipse“Variables”视图中,allPlainFields的值为**:** {Key1 =}
修改(27-FEB-2013):
试过这个,但没有用。这些值出现在jsp上,但是在提交时,它们不会起作用:
在Action
课程中:
private TreeMap<String,ObjectCList> testTreeMap = new TreeMap<String,ObjectCList>();
//get,set and setting two keys in map "mykey1" and "mykey2"
在ObjectCList
课程中:
private ArrayList<ObjectC> paramMdlList;
//default constructor, get, set
在JSP
:
<s:form id="test-map" method="post">
<s:iterator value="testTreeMap" var="pMap" status="hStatus">
<li><label><s:property value="%{#pMap.key}" /></label>
<s:iterator value="%{#pMap.value.paramMdlList}" var="pList" status="innerStatus">
<s:textfield name="testTreeMap['%{#pMap.key}'].paramMdlList[%{#innerStatus.index}].attr111"/>
<s:textfield name="testTreeMap['%{#pMap.key}'].paramMdlList[%{#innerStatus.index}].attr112"/>
</s:iterator>
</li>
</s:iterator>
<s:submit value=" " type='button' id="btnh1" action="saveTreeMap">
<span>Save TreeMap</span>
</s:submit>
</s:form>
提交表单后,会调用updateTreeMap
的{{1}}方法。地图按照here所述打印:
action
}
什么是“打印”: mykey1 / mykey2 / 即空值
下面的屏幕显示了jsp 中的值
答案 0 :(得分:6)
根据您的最新动态。如果您正在使用TreeMap
Struts2无法正确确定其中的元素类型。将testTreeMap
的声明从TreeMap
更改为Map
。
private Map<String,ObjectCList> testTreeMap = new TreeMap<String,ObjectCList>();
或使用testTreeMap
注释注释com.opensymphony.xwork2.util.Element
告诉Struts2地图中的元素是什么类型。
@Element(value = ObjectCList.class)
private TreeMap<String,ObjectCList> testTreeMap = new TreeMap<String,ObjectCList>();
答案 1 :(得分:5)
我变得好奇并做了其他实验。
我发现List
内的List
和Map
内的Map
s(以及所有内插)都没有声明为接口({{1} }},List
),或Map
正确处理其实现(ArrayList
,HashMap
,TreeMap
)。
所有测试用例都失败了。
也许这是我的错,如果是这样的话,我们真的需要一些XWork Converter
专家,因为在整个网络上都没有谈论这个。
然后我尝试了我非常确定会有效的方法:以纯OGNL
方式将此信息封装在自定义对象中。
它有效:)
而不是
OOP
您可以在操作
中使用private ArrayList<ArrayList<String>> outerObjects;
OuterObject 定义:
private ArrayList<OuterObject> outerObjects;
/* GETTERS AND SETTERS */
public ArrayList<OuterObject> getOuterObjects() {
return outerObjects;
}
public void setOuterObjects(ArrayList<OuterObject> outerObjects) {
this.outerObjects = outerObjects;
}
InnerObject 定义:
/* ELSEWHERE IN YOUR PROJECT... */
public class OuterObject{
private ArrayList<InnerObject> innerObjects;
/* GETTERS AND SETTERS */
public ArrayList<InnerObject> getInnerObjects() {
return innerObjects;
}
public void setInnerObjects(ArrayList<InnerObject> innerObjects) {
this.innerObjects = innerObjects;
}
}
操作的可选执行()方法,用于测试预设值:
public class InnerObject{
String innerField;
/* GETTERS AND SETTERS */
public String getInnerField() {
return innerField;
}
public void setInnerField(String innerField) {
this.innerField = innerField;
}
}
JSP :
InnerObject innerObj1 = new InnerObject();
innerObj1.setInnerField("Inner Value 1");
ArrayList<InnerObject> innerObjArrayList = new ArrayList<InnerObject>();
innerObjArrayList.add(innerObj1);
OuterObject outerObj1 = new OuterObject();
outerObj1.setInnerObjects(innerObjArrayList);
outerObjects = new ArrayList<OuterObject>();
outerObjects.add(outerObj1);
(在迭代时,只需使用 <s:form>
<s:textfield name="outerObjects[0].innerObjects[0].innerField" />
<s:submit/>
</s:form>
代表[%{#stat.index}]
s List
代表['%{#stat.index}']
s)
相同的解决方案适用于各种可迭代结构(可能除了需要调用Map
方法的Guava
内容之外)。
当然这在每种情况下都不方便,在你的例子中你已经有了一个巨大的结构并且这几乎会加倍,但它有效,它是OOP,你的OGNL会更清晰(因为但名称似乎是唯一的方式。
注意:类必须是真正的独立类,而不是.create()
,Inner Classes
无法自动装配对象的另一种情况。
希望有所帮助
编辑
您需要的只是另一个级别:
改变这个:
OGNL
到这个
private TreeMap<String,List<ObjectC>> allPlainFields;
并创建一个private TreeMap<String,ObjectX> allPlainFields;
,其中包含一个ObjectX
的私有字段。
它会起作用。