![](/img/trans.png)
[英]Passing a list of strings in a Spring MVC controller using Jquery Ajax
[英]Passing multiple variables in @RequestBody to a Spring MVC controller using Ajax
是否有必要包裹在支持对象中? 我想做这个:
@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"
}
}
那是对的吗? 我的另一个选择是将RequestMethod
更改为GET
并在查询字符串中使用@RequestParam
或将@PathVariable
与任一RequestMethod
一起使用。
你是对的,@RequestBody 注释参数应该包含请求的整个主体并绑定到一个对象,所以你基本上必须选择你的选项。
如果你绝对想要你的方法,你可以做一个自定义实现:
说这是你的json:
{
"str1": "test one",
"str2": "two test"
}
并且您想将其绑定到此处的两个参数:
@RequestMapping(value = "/Test", method = RequestMethod.POST)
public boolean getTest(String str1, String str2)
首先定义一个自定义注释,比如@JsonArg
,使用 JSON 路径,比如你想要的信息的路径:
public boolean getTest(@JsonArg("/str1") String str1, @JsonArg("/str2") String str2)
现在编写一个 Custom HandlerMethodArgumentResolver ,它使用上面定义的JsonPath来解析实际参数:
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 中注册它。 有点涉及,但这应该可以正常工作。
虽然@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"
用于传递多个对象、参数、变量等。 您可以使用 jackson 库中的 ObjectNode 作为参数动态执行此操作。 你可以这样做:
@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody ObjectNode objectNode) {
// And then you can call parameters from objectNode
String strOne = objectNode.get("str1").asText();
String strTwo = objectNode.get("str2").asText();
// When you using ObjectNode, you can pas other data such as:
// instance object, array list, nested object, etc.
}
我希望这会有所帮助。
您可以通过将 body 和 path 变量用于更简单的数据类型来混合 post 参数:
@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:/host/form_edit?param1=val1¶m2=val2
var1
& var2
是请求参数。
http:/host/form/{params}
{params}
是一个请求映射。 您可以像这样调用您的服务: http:/host/form/user
或http:/host/form/firm
其中公司和用户用作Pathvariable
。
简单的解决方案是创建一个具有 str1 和 str2 作为属性的负载类:
@Getter
@Setter
public class ObjHolder{
String str1;
String str2;
}
在你可以通过之后
@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody ObjHolder Str) {}
您的请求正文是:
{
"str1": "test one",
"str2": "two test"
}
您可以做简单的事情,而不是使用 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";
}
希望这对你有帮助。
我已经调整了Biju的解决方案:
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;
}
}
有什么不同:
BR
你也可以使用@RequestBody Map<String, String> params
,然后使用params.get("key")
来获取参数的值
您还可以使用 MultiValue Map 来保存 requestBody。这是它的示例。
foosId -> pathVariable
user -> extracted from the Map of request Body
与使用 Map 保存请求正文时的 @RequestBody 注释不同,我们需要使用 @RequestParam 进行注释
并在 Json RequestBody 中发送用户
@RequestMapping(value = "v1/test/foos/{foosId}", method = RequestMethod.POST, headers = "Accept=application"
+ "/json",
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE ,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String postFoos(@PathVariable final Map<String, String> pathParam,
@RequestParam final MultiValueMap<String, String> requestBody) {
return "Post some Foos " + pathParam.get("foosId") + " " + requestBody.get("user");
}
GET 和 POST 都存在请求参数,对于 Get 它将作为查询字符串附加到 URL 但对于 POST 它在请求正文中
不确定你在哪里添加 json 但如果我用 angular 这样做,它可以在没有 requestBody: angluar 的情况下工作:
const params: HttpParams = new HttpParams().set('str1','val1').set('str2', ;val2;);
return this.http.post<any>( this.urlMatch, params , { observe: 'response' } );
爪哇:
@PostMapping(URL_MATCH)
public ResponseEntity<Void> match(Long str1, Long str2) {
log.debug("found: {} and {}", str1, str2);
}
好的。 我建议创建一个包含您需要的字段的值对象 (Vo)。 代码更简单,我们不改变Jackson的功能,更容易理解。 问候!
您可以通过使用@RequestParam
来实现您想要的。 为此,您应该执行以下操作:
required
选项设置为 false。我知道,它有点黑客,但它有效! ;)
使用内部类
@RestController
public class MyController {
@PutMapping("/do-thing")
public void updateFindings(@RequestBody Bodies.DoThing body) {
...
}
private static class Bodies {
public static class DoThing {
public String name;
public List<String> listOfThings;
}
}
}
如果有人对 webflux 解决方案感兴趣,下面是一个基于 Biju 回答的反应式版本。
请注意,有一个非常小但同步的块,需要保护主体不被多次消耗。 如果你更喜欢完全非阻塞的版本,我建议在同一个调度器上发布获取 json 的通量,以进行检查和读取顺序。
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.MethodParameter; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.web.reactive.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.nio.charset.StandardCharsets; @Slf4j @RequiredArgsConstructor public class JsonArgumentResolver implements HandlerMethodArgumentResolver { private static final String ATTRIBUTE_KEY = "BODY_TOSTRING_RESOLVER"; private final ObjectMapper objectMapper; @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(JsonArgument.class); } @Override public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) { String fieldName = parameter.getParameterName(); Class<?> clz = parameter.getParameterType(); return getRequestBody(exchange).map(body -> { try { JsonNode jsonNode = objectMapper.readTree(body).get(fieldName); String s = jsonNode.toString(); return objectMapper.readValue(s, clz); } catch (JsonProcessingException e) { log.error(e.getMessage(), e); throw new RuntimeException(e); } }); } private Mono<String> getRequestBody(ServerWebExchange exchange) { Mono<String> bodyReceiver; synchronized (exchange) { bodyReceiver = exchange.getAttribute(ATTRIBUTE_KEY); if (bodyReceiver == null) { bodyReceiver = exchange.getRequest().getBody() .map(this::convertToString) .single() .cache(); exchange.getAttributes().put(ATTRIBUTE_KEY, bodyReceiver); } } return bodyReceiver; } private String convertToString(DataBuffer dataBuffer) { byte[] bytes = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(bytes); DataBufferUtils.release(dataBuffer); return new String(bytes, StandardCharsets.UTF_8); } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.