Przekazywanie wielu zmiennych w @RequestBody do kontrolera Spring MVC za pomocą Ajax
Czy konieczne jest owijanie w podkład? Chcę to zrobić:
@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody String str1, @RequestBody String str2) {}
I użyj JSON w ten sposób:
{
"str1": "test one",
"str2": "two test"
}
Ale zamiast tego muszę użyć:
@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody Holder holder) {}
A następnie użyj tego JSON:
{
"holder": {
"str1": "test one",
"str2": "two test"
}
}
Czy to prawda? Inną opcją jest zmiana RequestMethod
na GET
i użycie @RequestParam
w łańcuchu zapytania lub użycie @PathVariable
z RequestMethod
. 10 answers
Masz rację, oczekuje się, że parametr @RequestBody adnotowany będzie trzymał całą treść żądania i wiązał się z jednym obiektem, więc zasadniczo będziesz musiał przejść z opcjami.
Jeśli absolutnie chcesz swojego podejścia, istnieje niestandardowa implementacja, którą możesz zrobić: {]}
Powiedz, że to Twój json:
{
"str1": "test one",
"str2": "two test"
}
I chcesz powiązać to z dwoma paramami tutaj:
@RequestMapping(value = "/Test", method = RequestMethod.POST)
public boolean getTest(String str1, String str2)
Najpierw zdefiniuj niestandardową adnotację, powiedzmy @JsonArg
, ze ścieżką JSON podobną do ścieżki do informacje, które chcesz:
public boolean getTest(@JsonArg("/str1") String str1, @JsonArg("/str2") String str2)
Teraz napisz Niestandardowy HandlerMethodArgumentResolver który używa jsonpath zdefiniowanego powyżej, aby rozwiązać rzeczywisty argument:
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 "";
}
}
Teraz wystarczy zarejestrować to w Spring MVC. Trochę zaangażowany, ale to powinno działać czysto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-04 09:07:08
Chociaż prawdą jest, że @RequestBody
musi mapować do pojedynczego obiektu, ten obiekt może być Map
, więc to daje Ci dobrą drogę do tego ,co próbujesz osiągnąć (nie musisz pisać jednorazowego obiektu wspierającego):
@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody Map<String, String> json) {
//json.get("str1") == "test one"
}
Możesz również powiązać z ObjectNode jeśli chcesz mieć pełne drzewo JSON:
public boolean getTest(@RequestBody ObjectNode json) {
//json.get("str1").asText() == "test one"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-17 05:24:43
Możesz pomieszać argument post używając zmiennej body I path dla prostszych typów danych:
@RequestMapping(value = "new-trade/portfolio/{portfolioId}", method = RequestMethod.POST)
public ResponseEntity<List<String>> newTrade(@RequestBody Trade trade, @PathVariable long portfolioId) {
...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-09 18:35:23
@RequestParam
jest parametrem HTTP GET
lub POST
wysłanym przez Klienta, mapowanie żądań jest segmentem adresu URL, który jest zmienną:
http:/host/form_edit?param1=val1¶m2=val2
var1
& var2
są parami żądań.
http:/host/form/{params}
{params}
jest mapowaniem żądań. możesz zadzwonić do swojego serwisu jak: http:/host/form/user
lub http:/host/form/firm
gdzie Firma i użytkownik są używane jako Pathvariable
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-25 08:28:58
Zamiast używać json, możesz zrobić prostą rzecz.
$.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.>
});
Teraz w kontrolerze musisz odwzorować żądanie ajax jak poniżej:
@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";
}
Mam nadzieję, że to ci pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-15 12:15:44
Parametr Request istnieje zarówno dla GET, jak i POST ,dla Get zostanie dołączony jako ciąg zapytania do adresu URL, ale dla POST znajduje się w treści żądania
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-16 18:14:58
Zaadaptowałem rozwiązanie 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;
}
}
Czym się różni:
- używam Jacksona do konwersji json
- nie potrzebuję wartości w adnotacji, możesz odczytać nazwę parametr z MethodParameter
- odczytałem również typ parametru z Methodparameter = > więc rozwiązanie powinno być ogólne (testowałem je z string i DTOs)
BR
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-02 22:58:56
Nie wiem gdzie dodajesz json ale jeśli zrobię to tak z angular to działa bez requestBody: angluar: {]}
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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-22 20:53:41
Dobrze. Sugeruję stworzenie obiektu wartości (Vo), który zawiera pola, których potrzebujesz. Kod jest prostszy, nie zmieniamy funkcjonowania Jacksona i jest jeszcze łatwiejszy do zrozumienia. Pozdrawiam!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 19:41:12
Możesz osiągnąć to, co chcesz, używając @RequestParam
. W tym celu należy wykonać następujące czynności:
- Zadeklaruj parametry RequestParams, które reprezentują twoje obiekty i ustaw opcję
required
na false, jeśli chcesz móc wysłać wartość null. - na interfejsie użytkownika, stringify obiektów, które chcesz wysłać i dołącz je jako parametry żądania.
- na backendzie zamień ciągi JSON z powrotem w obiekty, które reprezentują za pomocą Jackson ObjectMapper lub coś w tym stylu, i voila!
Wiem, to trochę hack, ale to działa! ;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-26 19:12:05