Struts2:更新地图中“对象列表”的值
有一个对象ObjectA
,它有一个ObjectA
的列表。 TreeMap
有一个TreeMap
。 这个TreeMap
有一个String
作为键,另一个对象ObjectC
的List
作为值。 这个TreeMap
和里面的list
已经使用s:iterator
和s: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中的值
根据你最新的更新。 如果你正在使用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
,也没有Map
到Map
s(和所有插值),声明为接口( List
, Map
),或者作为它们的实现( ArrayList
, HashMap
, TreeMap
)被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>
的私有字段。
它会工作。