8

我正在尝试将 HashMap 或任何其他 Map 实现从 ajax 发送到 Spring MVC 控制器

这是我如何做的细节:

Ajax 调用如下

var tags = {};
tags["foo"] = "bar";
tags["whee"] = "whizzz";


$.post("doTestMap.do",   {"tags" : tags }, function(data, textStatus, jqXHR) {
if (textStatus == 'success') {
    //handle success
    console.log("doTest returned " + data);
} else {
    console.err("doTest returned " + data);
}
}); 

然后在控制器端我有:

@RequestMapping(value="/publisher/doTestMap.do", method=RequestMethod.POST)
public @ResponseBody String doTestMap(@RequestParam(value = "tags", defaultValue = "") HashMap<String,String> tags, HttpServletRequest request) {  //

    System.out.println(tags);

    return "cool";
} 

不幸的是,我系统地得到

org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'java.util.Map'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Map]: no matching editors or conversion strategy found

我究竟做错了什么 ?

谢谢你。

4

5 回答 5

13

在 Spring 控制器中绑定地图的方式与绑定数组相同。无需特殊转换器!

不过要记住一件事:

  • Spring使用命令对象作为顶级值持有者。命令对象可以是任何类。

因此,您所需要的只是一个包装类 ( TagsWrapper),它包含一个Map<String, String>称为标签的类型字段。与绑定数组相同的方法。

这在文档中得到了很好的解释,但我偶尔会忘记包装对象的需要;)

您需要更改的第二件事是提交标签值的方式:

  • 每个映射键使用一个表单参数,而不是完整映射的完整字符串表示。
  • 一个输入值应如下所示:

      <input type="text" name="tags[key]" value="something">
    

如果标签是包装器中的地图,则可以开箱即用地提交表单。

于 2013-08-17T05:43:39.980 回答
6

这是我根据 Martin Frey 的帮助用代码完成的答案:

javascript 方面(注意标签值是如何填充的):

var data = {
   "tags[foo]" : "foovalue", 
   "tags[whizz]" : "whizzvalue" 
}

$.post("doTestMap.do",   data , function(data, textStatus, jqXHR) {
    ...
}); 

然后在控制器端:

@RequestMapping(value="/publisher/doTestMap.do", method=RequestMethod.POST)
public @ResponseBody String doTestMap(@ModelAttribute MyWrapper wrapper, HttpServletRequest request) {
} 

并在其中创建带有 Map 的包装类:

class MyWrapper {

    Map<String,String> tags;

   +getters and setters

}

然后你会得到你的地图适当地填充......

于 2013-08-17T16:02:20.387 回答
5

这可能会迟到。但是,它可能会帮助某人。我有一个类似的问题,这就是我解决它的方法。在 JS 上:我的地图看起来像,

var values = {};
values[element.id] = element.value;

阿贾克斯:

        $.ajax({
            type : 'POST',
            url : 'xxx.mvc',
            data : JSON.stringify(values),              
            error : function(response) {
                alert("Operation failed.");
            },
            success : function(response) {
                alert("Success");
            },
            contentType : "application/json",
            dataType : "json"
        });

控制器:

@RequestMapping(value = "/xxx.mvc", method=RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getValues(@RequestBody Map<String, Object> pvmValues, final HttpServletRequest request, final HttpServletResponse response) {
System.out.println(pvmValues.get("key"));
}
于 2014-10-03T14:40:25.933 回答
0

The best way of doing this would be encoding the object using JSON and decoding it.

You need two libraries. On the client side you need json2.js. Some browsers seem to natively do this by now. But having this is the safer way.

On the server you need jackson.

On the client you encode your map and pass that as parameter:

var myEncodedObject = JSON.stringify(tags);

On the server you receive the parameter as a string and decode it:

ObjectMapper myMapper = new ObjectMapper();
Map<String, Object> myMap = myMapper.readValue(tags, new TypeReference<Map<String, Object>>);

There may be some way in Spring to make it convert automatically, but this is the gist of it.

于 2013-08-17T02:33:32.753 回答
0

您正在发送一个 javascript 数组tags,默​​认情况下,jQuery 会将其 url 编码为一系列名为tags[]. 不确定这是否是您想要的。

你会得到一个错误,因为 spring 没有从多个同名参数到HashMap. 但是,它可以轻松地将它们转换为List、 数组或Set.

所以试试这个:

@RequestMapping(value="/publisher/doTestMap.do", method=RequestMethod.POST)
public @ResponseBody String doTestMap(@RequestParam(value = "tags[]") Set<String> tags, HttpServletRequest request) {  //

    System.out.println(tags); //this probably won't print what you want

    return "cool";
} 
于 2013-08-17T01:26:45.780 回答