Est-il nécessaire d'envelopper un objet de support? Je veux faire ça:
@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody String str1, @RequestBody String str2) {}
Et utilisez un JSON comme ceci:
{
"str1": "test one",
"str2": "two test"
}
Mais au lieu de cela, je dois utiliser:
@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody Holder holder) {}
Et puis utilisez ce JSON:
{
"holder": {
"str1": "test one",
"str2": "two test"
}
}
Est-ce exact? Mon autre option serait de changer la RequestMethod
en GET
et d'utiliser @RequestParam
dans la chaîne de requête ou d'utiliser @PathVariable
avec soit RequestMethod
.
Vous avez raison, le paramètre annoté @RequestBody est censé contenir tout le corps de la demande et se lier à un seul objet. Vous devrez donc choisir vos options.
Si vous voulez absolument votre approche, vous pouvez faire une implémentation personnalisée:
Dis que c'est ton json:
{
"str1": "test one",
"str2": "two test"
}
et vous voulez le lier aux deux params ici:
@RequestMapping(value = "/Test", method = RequestMethod.POST)
public boolean getTest(String str1, String str2)
Commencez par définir une annotation personnalisée, par exemple @JsonArg
, avec le chemin JSON comme chemin d'accès aux informations souhaitées:
public boolean getTest(@JsonArg("/str1") String str1, @JsonArg("/str2") String str2)
Maintenant, écrivez un Custom HandlerMethodArgumentResolver qui utilise le JsonPath défini ci-dessus pour résoudre l’argument actuel:
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 "";
}
}
Maintenant, enregistrez ceci avec Spring MVC. Un peu impliqué, mais cela devrait fonctionner proprement.
S'il est vrai que @RequestBody
doit mapper sur un seul objet, cet objet peut être une Map
, ce qui vous permet d'obtenir un bon moyen d'atteindre vos objectifs (inutile d'écrire un objet unique):
@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody Map<String, String> json) {
//json.get("str1") == "test one"
}
Vous pouvez également vous connecter au ObjectNode de Jackson si vous voulez une arborescence JSON complète:
public boolean getTest(@RequestBody ObjectNode json) {
//json.get("str1").asText() == "test one"
Vous pouvez mélanger l'argument post en utilisant la variable body et path pour des types de données plus simples:
@RequestMapping(value = "new-trade/portfolio/{portfolioId}", method = RequestMethod.POST)
public ResponseEntity<List<String>> newTrade(@RequestBody Trade trade, @PathVariable long portfolioId) {
...
}
@RequestParam
est le paramètre HTTP GET
ou POST
envoyé par le client, le mappage de demande est un segment d'URL dont la variable est:
http:/Host/form_edit?param1=val1¶m2=val2
var1
& var2
sont des paramètres de demande.
http:/Host/form/{params}
{params}
est un mappage de demande. vous pouvez appeler votre service comme suit: http:/Host/form/user
ou http:/Host/form/firm
où firm et user sont utilisés comme Pathvariable
.
Pour transmettre plusieurs objets, paramètres, variables, etc. Vous pouvez le faire dynamiquement en utilisant ObjectNode à partir de la bibliothèque jackson comme paramètre. Vous pouvez le faire comme ça:
@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.
}
J'espère que cette aide.
Vous pouvez obtenir ce que vous voulez en utilisant @RequestParam
. Pour cela, vous devriez faire ce qui suit:
required
sur false si vous souhaitez pouvoir envoyer une valeur null.Je sais, c'est un peu un bidouillage mais ça marche! ;)
Je ne sais pas où vous ajoutez le JSON mais si je le fais comme ça avec angular cela fonctionne sans le requestBody:
const params: HttpParams = new HttpParams().set('str1','val1').set('str2', ;val2;);
return this.http.post<any>( this.urlMatch, params , { observe: 'response' } );
Java:
@PostMapping(URL_MATCH)
public ResponseEntity<Void> match(Long str1, Long str2) {
log.debug("found: {} and {}", str1, str2);
}
Bon .. Je suggère de créer un objet de valeur (Vo) contenant les champs dont vous avez besoin. Le code est plus simple, nous ne changeons pas le fonctionnement de Jackson et il est encore plus facile à comprendre . Cordialement!
vous pouvez également utiliser @RequestBody Map<String, String> params
, puis utiliser params.get("key")
pour obtenir la valeur du paramètre
le paramètre request existe pour GET et POST. Pour Get, il sera ajouté en tant que chaîne de requête à l'URL, mais pour POST, il figure dans le corps de la requête.
J'ai adapté la solution de 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;
}
}
Quelle est la différence:
BR
Au lieu d'utiliser JSON, vous pouvez faire quelque chose de simple.
$.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.>
});
Maintenant, dans le contrôleur, vous devez mapper la demande ajax comme ci-dessous:
@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";
}
J'espère que cela vous aide.