将@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
,或使用@PathVariable
和RequestMethod
。
你是正确的,@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