将@RequestBody中的多个variables传递给使用Ajax的Spring MVC控制器

是否需要包装在后台对象? 我想做这个:

@RequestMapping(value = "/Test", method = RequestMethod.POST) @ResponseBody public boolean getTest(@RequestBody String str1, @RequestBody String str2) {} 

并使用这样的JSON:

 { "str1": "test one", "str2": "two test" } 

但是,我不得不使用:

 @RequestMapping(value = "/Test", method = RequestMethod.POST) @ResponseBody public boolean getTest(@RequestBody Holder holder) {} 

然后使用这个JSON:

 { "holder": { "str1": "test one", "str2": "two test" } } 

那是对的吗? 我的另一种select是将RequestMethod更改为GET并在查询string中使用@RequestParam ,或使用@PathVariableRequestMethod

你是正确的,@RequestBody注释参数预计将持有整个请求的身体并绑定到一个对象,所以你基本上将不得不去与你的select。

如果你绝对想要你的方法,你可以做一个自定义的实现:

说这是你的json:

 { "str1": "test one", "str2": "two test" } 

你想在这里绑定它的两个参数:

 @RequestMapping(value = "/Test", method = RequestMethod.POST) public boolean getTest(String str1, String str2) 

首先使用JSONpath定义一个自定义注释,比如@JsonArg ,就像所需信息的path一样:

 public boolean getTest(@JsonArg("/str1") String str1, @JsonArg("/str2") String str2) 

现在编写一个Custom HandlerMethodArgumentResolver ,它使用上面定义的JsonPath来parsing实际的参数:

 import java.io.IOException; import javax.servlet.http.HttpServletRequest; import org.apache.commons.io.IOUtils; import org.springframework.core.MethodParameter; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import com.jayway.jsonpath.JsonPath; public class JsonPathArgumentResolver implements HandlerMethodArgumentResolver{ private static final String JSONBODYATTRIBUTE = "JSON_REQUEST_BODY"; @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(JsonArg.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { String body = getRequestBody(webRequest); String val = JsonPath.read(body, parameter.getMethodAnnotation(JsonArg.class).value()); return val; } private String getRequestBody(NativeWebRequest webRequest){ HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); String jsonBody = (String) servletRequest.getAttribute(JSONBODYATTRIBUTE); if (jsonBody==null){ try { String body = IOUtils.toString(servletRequest.getInputStream()); servletRequest.setAttribute(JSONBODYATTRIBUTE, body); return body; } catch (IOException e) { throw new RuntimeException(e); } } return ""; } } 

现在只需在Spring MVC中注册。 有一点涉及,但这应该干净地工作。

尽pipe@RequestBody必须映射到一个对象,但是这个对象可以是一个Map ,所以这可以让你得到一个很好的方法来实现你正在尝试实现的内容(不需要写一个一次性的后台对象):

 @RequestMapping(value = "/Test", method = RequestMethod.POST) @ResponseBody public boolean getTest(@RequestBody Map<String, String> json) { //json.get("str1") == "test one" } 

如果您想要一个完整的JSON树,您还可以绑定到Jackson的ObjectNode :

 public boolean getTest(@RequestBody ObjectNode json) { //json.get("str1").asText() == "test one" 

你可以通过使用body和pathvariables来简化post数据types:

 @RequestMapping(value = "new-trade/portfolio/{portfolioId}", method = RequestMethod.POST) public ResponseEntity<List<String>> newTrade(@RequestBody Trade trade, @PathVariable long portfolioId) { ... } 

@RequestParam是客户端发送的HTTP GET或POST参数,请求映射是可变的一段URL:

HTTP:/主机/ form_edit参数1 = VAL1&param2的= val2的

var1&var2是requestparams。

HTTP:/主机/forms/ {PARAMS}

{params}是一个请求映射。 你可以打电话给你的服务:http:/ host / form / user或http:/ host / form / firm,其中公司和用户被用作Pathvariable。

而不是使用json,你可以做简单的事情。

 $.post("${pageContext.servletContext.contextPath}/Test", { "str1": "test one", "str2": "two test", <other form data> }, function(j) { <j is the string you will return from the controller function.> }); 

现在在控制器中,您需要如下所示映射ajax请求:

  @RequestMapping(value="/Test", method=RequestMethod.POST) @ResponseBody public String calculateTestData(@RequestParam("str1") String str1, @RequestParam("str2") String str2, HttpServletRequest request, HttpServletResponse response){ <perform the task here and return the String result.> return "xyz"; } 

希望这可以帮助你。

请求参数对于GET和POST都是存在的,对于Get,它将作为查询string追加到URL中,但对于POST,它在Request Body中

我已经适应了Biju的解决scheme:

 import java.io.IOException; import javax.servlet.http.HttpServletRequest; import org.apache.commons.io.IOUtils; import org.springframework.core.MethodParameter; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonPathArgumentResolver implements HandlerMethodArgumentResolver{ private static final String JSONBODYATTRIBUTE = "JSON_REQUEST_BODY"; private ObjectMapper om = new ObjectMapper(); @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(JsonArg.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { String jsonBody = getRequestBody(webRequest); JsonNode rootNode = om.readTree(jsonBody); JsonNode node = rootNode.path(parameter.getParameterName()); return om.readValue(node.toString(), parameter.getParameterType()); } private String getRequestBody(NativeWebRequest webRequest){ HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); String jsonBody = (String) webRequest.getAttribute(JSONBODYATTRIBUTE, NativeWebRequest.SCOPE_REQUEST); if (jsonBody==null){ try { jsonBody = IOUtils.toString(servletRequest.getInputStream()); webRequest.setAttribute(JSONBODYATTRIBUTE, jsonBody, NativeWebRequest.SCOPE_REQUEST); } catch (IOException e) { throw new RuntimeException(e); } } return jsonBody; } } 

有什么不同:

  • 我正在使用jackson来转换JSON
  • 我不需要注释中的值,您可以从MethodParameter中读取参数的名称
  • 我也从Methodparameter =>读取参数的types,所以解决scheme应该是通用的(我testing它与string和DTOs)

BR