Struts2:更新地图中“对象列表”的值

有一个对象ObjectA ,它有一个ObjectA的列表。 TreeMap有一个TreeMap 。 这个TreeMap有一个String作为键,另一个对象ObjectCList作为值。 这个TreeMap和里面的list已经使用s:iterators:textfield显示在jsp上,并且显示正确。 即s:textfield中的“值”是正确的。 现在,当文本字段被修改时出现问题。 我们如何在动作类中捕获ObjectC中的修改值? 用这里给出的代码,键(“Key1”)进来的动作,但值为空。

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">

日食“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 =}

编辑(2013年2月27日)

试过这个,但没有工作。 这些值出现在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> 

当表单被提交时, action updateTreeMap方法被调用。 地图打印如上所述:

 public String updateTreeMap(){ for (Map.Entry<String, ObjectCList> entry : testTreeMap.entrySet()) { System.out.println(entry.getKey() + "/" + entry.getValue()); } return SUCCESS; 

}

什么是“打印”:mykey1 / mykey2 /即空值

下面的屏幕显示了jsp中的值 屏幕显示值来自jsp

根据你最新的更新。 如果你正在使用TreeMap Struts2不能正确地确定它里面的元素的types。 将testTreeMap声明更改为Map

 private Map<String,ObjectCList> testTreeMap = new TreeMap<String,ObjectCList>(); 

或者使用com.opensymphony.xwork2.util.Element注释来注释testTreeMap ,以告诉Struts2 map中的元素是什么types。

 @Element(value = ObjectCList.class) private TreeMap<String,ObjectCList> testTreeMap = new TreeMap<String,ObjectCList>(); 

我变得好奇,做了其他的实验。

我发现List s中没有List ,也没有MapMap s(和所有插值),声明为接口( ListMap ),或者作为它们的实现( ArrayListHashMapTreeMap )被XWork Converter正确处理XWork Converter

所有的testing案例都失败了。

也许这是我的错,如果是这样的话,我们确实需要一些OGNL专家,因为在整个networking上,没有什么可以谈论这个的。

然后,我尝试了一下我很确定的工作:将这些信息封装在自定义对象中 ,采用纯粹的OOP方式。

它的工作:)

代替

 private ArrayList<ArrayList<String>> outerObjects; 

你可以在你的Action中使用

 private ArrayList<OuterObject> outerObjects; /* GETTERS AND SETTERS */ public ArrayList<OuterObject> getOuterObjects() { return outerObjects; } public void setOuterObjects(ArrayList<OuterObject> outerObjects) { this.outerObjects = outerObjects; } 

OuterObject定义:

 /* 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; } } 

InnerObject定义:

 public class InnerObject{ String innerField; /* GETTERS AND SETTERS */ public String getInnerField() { return innerField; } public void setInnerField(String innerField) { this.innerField = innerField; } } 

您的Action的可选execute()方法来testing预设值:

  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); 

JSP

  <s:form> <s:textfield name="outerObjects[0].innerObjects[0].innerField" /> <s:submit/> </s:form> 

(在迭代时,只需使用[%{#stat.index}]作为List s和['%{#stat.index}']作为Map s)

同样的解决scheme适用于每种types的可迭代结构(可能除了需要调用.create()方法的Guava外)。

当然,这在每种情况下都是不方便的,在你的例子中,你已经有了一个巨大的结构, 而且这个结构几乎翻了一番 ,但是它是有效的,它是OOP,你的OGNL会更清晰(因为名字),但似乎是唯一的办法。

注意:类必须是真正的独立类,而不是Inner Classes ,这是OGNL无法自动装载对象的另一种情况。

希望有所帮助


编辑

那么你需要什么,只有一个层面:

改变这个:

 private TreeMap<String,List<ObjectC>> allPlainFields; 

对此

 private TreeMap<String,ObjectX> allPlainFields; 

并创build一个ObjectX其中包含一个List<ObjectC>的私有字段。

它会工作。