Ajax를 사용하여 @RequestBody의 여러 변수를 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"
}
}
그 맞습니까? 내 다른 옵션은 변경하는 것 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)
이제 실제 인수를 해결하기 위해 위에 정의 된 JsonPath 를 사용 하는 Custom HandlerMethodArgumentResolver 를 작성합니다 .
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"
더 간단한 데이터 유형에 대해 본문 및 경로 변수를 사용하여 post 인수를 혼합 할 수 있습니다.
@RequestMapping(value = "new-trade/portfolio/{portfolioId}", method = RequestMethod.POST)
public ResponseEntity<List<String>> newTrade(@RequestBody Trade trade, @PathVariable long portfolioId) {
...
}
여러 객체, 매개 변수, 변수 등을 전달합니다. 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.
}
도움이 되었기를 바랍니다.
@RequestParam
is the HTTP GET
or POST
parameter sent by client, request mapping is a segment of URL which's variable:
http:/host/form_edit?param1=val1¶m2=val2
var1
& var2
are request params.
http:/host/form/{params}
{params}
is a request mapping. you could call your service like : http:/host/form/user
or http:/host/form/firm
where firm & user are used as Pathvariable
.
Instead of using json, you can do simple thing.
$.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.>
});
Now in the controller you need to map the ajax request as below:
@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";
}
Hope this helps you.
request parameter exist for both GET and POST ,For Get it will get appended as query string to URL but for POST it is within Request Body
I have adapted the solution of 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;
}
}
What's the different:
- I'm using Jackson to convert json
- I don't need a value in the annotation, you can read the name of the parameter out of the MethodParameter
- I also read the type of the parameter out of the Methodparameter => so the solution should be generic (i tested it with string and DTOs)
BR
Not sure where you add the json but if i do it like this with angular it works without the 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);
}
Good. I suggest creating a Value Object (Vo) that contains the fields you need. The code is simpler, we do not change the functioning of Jackson and it is even easier to understand. Regards!
You can achieve what you want by using @RequestParam
. For this you should do the following:
- Declare the RequestParams parameters that represent your objects and set the
required
option to false if you want to be able to send a null value. - On the frontend, stringify the objects that you want to send and include them as request parameters.
- On the backend turn the JSON strings back into the objects they represent using Jackson ObjectMapper or something like that, and voila!
I know, its a bit of a hack but it works! ;)
you can also user @RequestBody Map<String, String> params
,then use params.get("key")
to get the value of parameter
'development' 카테고리의 다른 글
Hystrix에서 사용하는 벌크 헤드 패턴은 무엇입니까? (0) | 2020.09.07 |
---|---|
302 리디렉션이 리퍼러 문자열을 유지합니까? (0) | 2020.09.07 |
컴파일러가 do-while 루프에 대해 다른 유형의 루프에 비해 더 나은 코드를 생성합니까? (0) | 2020.09.07 |
.NET 용 XPath 및 XSLT 2.0? (0) | 2020.09.07 |
CMake는 어떻게 사용하나요? (0) | 2020.09.07 |