Spring MVC-@RequestBody와 @RequestParam을 함께 사용할 수없는 이유
Post request 및 Content-Type application / x-www-form-urlencoded와 함께 HTTP dev 클라이언트 사용
1) @RequestBody 만
요청-localhost : 8080 / SpringMVC / welcome In Body-name = abc
암호-
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, Model model) {
model.addAttribute("message", body);
return "hello";
}
// 예상대로 본문에 'name = abc'를 제공합니다.
2) @RequestParam 만
요청-localhost : 8080 / SpringMVC / welcome In Body-name = abc
암호-
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestParam String name, Model model) {
model.addAttribute("name", name);
return "hello";
}
// 예상대로 이름을 'abc'로 지정
3) 둘 다 함께
요청-localhost : 8080 / SpringMVC / welcome In Body-name = abc
암호-
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, @RequestParam String name, Model model) {
model.addAttribute("name", name);
model.addAttribute("message", body);
return "hello";
}
// HTTP 오류 코드 400-클라이언트가 보낸 요청이 구문 상 잘못되었습니다.
4) 위의 매개 변수 위치 변경
요청-localhost : 8080 / SpringMVC / welcome In Body-name = abc
암호-
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestParam String name, @RequestBody String body, Model model) {
model.addAttribute("name", name);
model.addAttribute("message", body);
return "hello";
}
// 오류 없음. 이름은 'abc'입니다. 본문이 비어 있습니다
5) 함께 있지만 유형 URL 매개 변수 가져 오기
요청-localhost : 8080 / SpringMVC / welcome? name = xyz In Body-name = abc
암호-
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, @RequestParam String name, Model model) {
model.addAttribute("name", name);
model.addAttribute("message", body);
return "hello";
}
// 이름은 'xyz'이고 본문은 'name = abc'입니다.
6) 5)와 동일하지만 매개 변수 위치가 변경됨
코드-
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestParam String name, @RequestBody String body, Model model) {
model.addAttribute("name", name);
model.addAttribute("message", body);
return "hello";
}
// name = 'xyz, abc'body is empty
누군가이 행동을 설명 할 수 있습니까?
@RequestBody
javadoc의 상태
메서드 매개 변수를 나타내는 주석은 웹 요청 본문에 바인딩되어야합니다.
의 등록 된 인스턴스를 사용 HttpMessageConverter
하여 요청 본문을 주석이 달린 매개 변수 유형의 객체로 역 직렬화합니다.
과 @RequestParam
메서드 매개 변수가 웹 요청 매개 변수에 바인딩되어야 함을 나타내는 주석입니다.
Spring은 요청 본문을로 주석이 달린 매개 변수에 바인딩합니다
@RequestBody
.Spring은 요청 본문 (URL 인코딩 매개 변수)의 요청 매개 변수를 메소드 매개 변수에 바인딩합니다. Spring은 매개 변수의 이름을 사용합니다.
name
, 매개 변수를 매핑합니다.Parameters are resolved in order. The
@RequestBody
is processed first. Spring will consume all theHttpServletRequest
InputStream
. When it then tries to resolve the@RequestParam
, which is by defaultrequired
, there is no request parameter in the query string or what remains of the request body, ie. nothing. So it fails with 400 because the request can't be correctly handled by the handler method.The handler for
@RequestParam
acts first, reading what it can of theHttpServletRequest
InputStream
to map the request parameter, ie. the whole query string/url-encoded parameters. It does so and gets the valueabc
mapped to the parametername
. When the handler for@RequestBody
runs, there's nothing left in the request body, so the argument used is the empty string.The handler for
@RequestBody
reads the body and binds it to the parameter. The handler for@RequestParam
can then get the request parameter from the URL query string.The handler for
@RequestParam
reads from both the body and the URL query String. It would usually put them in aMap
, but since the parameter is of typeString
, Spring will serialize theMap
as comma separated values. The handler for@RequestBody
then, again, has nothing left to read from the body.
It's too late to answer this question, but it could help for new readers, It seems version issues. I ran all these tests with spring 4.1.4 and found that the order of @RequestBody
and @RequestParam
doesn't matter.
- same as your result
- same as your result
- gave
body= "name=abc"
, andname = "abc"
- Same as 3.
body ="name=abc"
,name = "xyz,abc"
- same as 5.
It happens because of not very straight forward Servlet specification. If you are working with a native HttpServletRequest
implementation you cannot get both the URL encode body and the parameters. Spring does some workarounds, which make it even more strange and nontransparent.
In such cases Spring (version 3.2.4) re-renders a body for you using data from the getParameterMap()
method. It mixes GET and POST parameters and breaks the parameter order. The class, which is responsible for the chaos is ServletServerHttpRequest
. Unfortunately it cannot be replaced, but the class StringHttpMessageConverter
can be.
The clean solution is unfortunately not simple:
- Replacing
StringHttpMessageConverter
. Copy/Overwrite the original class adjusting methodreadInternal()
. - Wrapping
HttpServletRequest
overwritinggetInputStream()
,getReader()
andgetParameter*()
methods.
In the method StringHttpMessageConverter#readInternal following code must be used:
if (inputMessage instanceof ServletServerHttpRequest) {
ServletServerHttpRequest oo = (ServletServerHttpRequest)inputMessage;
input = oo.getServletRequest().getInputStream();
} else {
input = inputMessage.getBody();
}
Then the converter must be registered in the context.
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true/false">
<bean class="my-new-converter-class"/>
</mvc:message-converters>
</mvc:annotation-driven>
The step two is described here: Http Servlet request lose params from POST body after read it once
You could also just change the @RequestParam default required status to false so that HTTP response status code 400 is not generated. This will allow you to place the Annotations in any order you feel like.
@RequestParam(required = false)String name
ReferenceURL : https://stackoverflow.com/questions/19468572/spring-mvc-why-not-able-to-use-requestbody-and-requestparam-together
'IT story' 카테고리의 다른 글
Java에서 데스크탑 경로를 얻는 방법 (0) | 2020.12.31 |
---|---|
gc ()가 메모리를 해제하지 않는 이유는 무엇입니까? (0) | 2020.12.31 |
addlash ()를 통한 SQL 주입의 예? (0) | 2020.12.31 |
someString.IndexOf (someString)은 .NET 4에서 0 대신 1을 반환합니다. (0) | 2020.12.31 |
VisualStudio Community 2013에서 평가판 라이선스를 업데이트하라는 메시지가 표시됨 (0) | 2020.12.31 |