将Mapped属性与Struts中的Indexed属性相结合

时间:2010-09-15 17:41:04

标签: java java-ee struts

我正在尝试使用动态表单,并且根据属性类型,我想显示不同的输入样式(文本字段,单选按钮,下拉列表,清单......)。

为了获得动态表单,我使用Map设置了ActionForm。

Map<String, Object> values;
public void setValue(String key, Object value);
public Object getValue(String key);

当我尝试设置清单或多功能箱时出现问题。 ActionForm只传递一个值,尽管我希望String []可以映射到Object参数。

关于如何解决这个问题的任何想法?

编辑:在JSP中:

<input type=checkbox name="value(foo)" />

1 个答案:

答案 0 :(得分:1)

我调查了这个问题,发现了发生了什么。问题不在于Struts,而在于BeanUtils(Struts用它来填充带有请求参数的表单)。

我设法通过从框架中提取(仅测试)代码片段来复制它:

public class MyForm {
  // assume this is your Struts ActionForm
  public void setValue(String key, Object val) {
    System.out.println(key + "=" + val);
  }
}

public class Test {
  public static void main(String[] args) 
      throws IllegalAccessException, InvocationTargetException {
    MyForm s = new MyForm();
    Map<String, Object> properties = new HashMap<String, Object>();
    // Your request should be like yourActionUrl?value(foo)=1&value(foo)=2&value(foo)=3 
    // and Struts calls bean utils with something like:
    properties.put("value(foo)", new String[] {"1", "2", "3"});
    BeanUtils.populate(s, properties);
  }
}

当你运行它时,你只会打印一个值(正如你所说的那样):

foo=1

问题是BeanUtils认为这是一个映射属性并将其视为这样,为密钥的标量值。由于您的值是数组,因此它只使用第一个元素:

...
} else if (value instanceof String[]) {
  newValue = getConvertUtils().convert(((String[]) value)[0], type);
...

您可以做的是修改JSP和ActionForm以分别处理值列表。修改示例:

public class MyForm {
  private Map<String, Object> map = new HashMap<String, Object>();

  public void setValue(String key, Object val) {
    map.put(key, val);
  }

  public void setPlainValue(String[] values) {
    // this is correctly called; now delegate to what you really wanted 
    setValue("foo", values);
  }
}

public class Test {
  public static void main(String[] args) 
      throws IllegalAccessException, InvocationTargetException {
    MyForm s = new MyForm();
    Map<String, Object> properties = new HashMap<String, Object>();
    // Notice the change to your URL..
    // yourActionUrl?plainValue=1&plainValue=2&plainValue=3
    properties.put("plainValue", new String[] {"1", "2", "3"});
    BeanUtils.populate(s, properties);
  }
}

以上表示您使用

<input type="..." name="value(foo)" ... />

对于JSP中的所有单个元素,对于复选框(通常将其扩展为多值元素),您可以使用

<input type="checkbox" name="plainValue" ... />

并在ActionForm中委托一次地图。