programing

Spring MVC - @RequestBody와 @RequestParam을 함께 사용할 수 없는 이유

bestprogram 2023. 10. 19. 22:37

Spring MVC - @RequestBody와 @RequestParam을 함께 사용할 수 없는 이유

Post request 및 Content-Type 응용 프로그램/x-www-form-urlencoded에서 HTTP 개발 클라이언트 사용

1) @RequestBody만

URL: localhost:8080/SpringMVC/welcome
본문 : 이름=

@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, Model model) {
    model.addAttribute("message", body);
    return "hello";
}
// Gives body as 'name=abc' as expected

2) @RequestParam만

URL: localhost:8080/SpringMVC/welcome
본문 - name=

@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestParam String name, Model model) {
    model.addAttribute("name", name);
    return "hello";
}
// Gives name as 'abc' as expected

3) 둘다 같이

URL: localhost:8080/SpringMVC/welcome
본문 : 이름=

@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 Error Code 400 - The request sent by the client was syntactically incorrect.

4) 위에서 매개변수 위치가 변경됨

URL: localhost:8080/SpringMVC/welcome
본문 : 이름=

@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";
}
// No Error. Name  is 'abc'. body is empty

5) 함께 있지만 유형 URL 매개 변수 가져오기

URL: localhost:8080/SpringMVC/welcome?name=xyz
본문 : 이름=

@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";
}
// name is 'xyz' and body is '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자바도크 주

메서드 매개 변수를 나타내는 주석은 웹 요청 본문에 바인딩되어야 합니다.

등록된 인스턴스(instance)HttpMessageConverter요청 본문을 주석이 달린 매개 변수 유형의 개체로 역직렬화합니다.

그리고.@RequestParam자바도크 주

메서드 매개 변수가 웹 요청 매개 변수에 바인딩되어야 함을 나타내는 주석입니다.

  1. 스프링은 요청 본문을 다음과 같이 주석이 달린 매개 변수에 바인딩합니다.@RequestBody.

  2. Spring은 요청 본문의 요청 매개 변수(url-encoded parameter)를 메서드 매개 변수에 바인딩합니다.Spring은 매개 변수의 이름을 사용합니다. 즉,name, 파라미터를 매핑합니다.

  3. 매개 변수는 순서대로 해결됩니다.@RequestBody먼저 처리됩니다.봄은 모든 것을 소비할 것입니다.HttpServletRequest InputStream. 그 다음에 그것이 해결하려고 할 때@RequestParam, 기본적으로required, 쿼리 문자열에 요청 매개 변수가 없거나 요청 본문에 남아 있는 것, 즉 아무것도 없습니다.따라서 핸들러 방식으로는 요청을 올바르게 처리할 수 없기 때문에 400으로 실패합니다.

  4. 처리자:@RequestParam먼저 행동하고, 그것이 할 수 있는 것을 읽습니다.HttpServletRequest InputStream요청 매개 변수, 즉 전체 쿼리 문자열/url-encoded 매개 변수를 매핑합니다.그렇게 해서 가치를 얻게 됩니다.abc매개 변수에 매핑된name. 처리자가 다음을 수행할 때@RequestBodyruns, 요청 본문에는 아무것도 남지 않으므로 사용되는 인수는 빈 문자열입니다.

  5. 처리자:@RequestBody본문을 읽고 파라미터에 바인딩합니다.처리자:@RequestParam그런 다음 URL 쿼리 문자열에서 요청 매개 변수를 가져올 수 있습니다.

  6. 의 :@RequestParam본문과 URL 쿼리 String에서 모두 읽습니다.그것은 보통 그들을 A에 넣곤 했습니다.Map, 그러나 매개 변수가 유형이기 때문에String, 봄이 그들을 연재할 것입니다.Map쉼표로 구분된 값으로.자의 :@RequestBody그리고 다시, 몸에서 읽을 것이 아무것도 남지 않았습니다.

이 질문에 답하기에는 너무 늦었지만, 새로운 독자들에게 도움이 될 수도 있습니다. 버전 문제인 것 같습니다.스프링 4.1.4로 이 모든 테스트를 실행한 결과,@RequestBody그리고.@RequestParam상관없어.

  1. 자네의 결과와 같은
  2. 자네의 결과와 같은
  3. 줬다body= "name=abc",그리고.name = "abc"
  4. 3과 같습니다.
  5. body ="name=abc",name = "xyz,abc"
  6. 5와 같은

이는 매우 간단한 서블릿 사양 때문에 발생합니다.현지인과 함께 작업하는 경우HttpServletRequest구현 URL 인코딩 본문과 매개 변수를 둘 다 얻을 수 없습니다.봄은 몇 가지 해결책을 제공하는데, 이것은 봄을 더욱 이상하고 투명하게 만듭니다.

이 경우 Spring(버전 3.2.4)은 데이터를 사용하여 본체를 다시 렌더링합니다.getParameterMap()방법.GET 파라미터와 POST 파라미터를 혼합하여 파라미터 순서를 바꿉니다.GET 파라미터와 POST 파라미터를 혼합하고 파라미터 순서를 바꿉니다.혼란의 책임이 있는 학급은ServletServerHttpRequest. 유감스럽게도 그것은 대체할 수 없지만, 클래스는StringHttpMessageConverter수 있습니다.

깨끗한 해결책은 불행히도 간단하지 않습니다.

  1. StringHttpMessageConverter. 원래 클래스 조정 방법 복사/ 덮어쓰기readInternal().
  2. HttpServletRequest덮어쓰기getInputStream(),getReader()그리고.getParameter*()방법들.

StringHttpMessageConverter#read 메서드에서내부 다음 코드를 사용해야 합니다.

    if (inputMessage instanceof ServletServerHttpRequest) {
        ServletServerHttpRequest oo = (ServletServerHttpRequest)inputMessage;
        input = oo.getServletRequest().getInputStream();
    } else {
        input = inputMessage.getBody();
    }

그러면 컨텍스트에 컨버터를 등록해야 합니다.

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true/false">
        <bean class="my-new-converter-class"/>
   </mvc:message-converters>
</mvc:annotation-driven>

2단계는 여기에 설명되어 있습니다.Http Servlet 요청이 POST 본문에서 한 번 읽은 후에 매개 변수가 손실됨

HTTP 응답 상태 코드 400이 생성되지 않도록 @RequestParam default required status를 false로 변경할 수도 있습니다.이렇게 하면 원하는 순서대로 주석을 배치할 수 있습니다.

@RequestParam(required = false)String name

언급URL : https://stackoverflow.com/questions/19468572/spring-mvc-why-not-able-to-use-requestbody-and-requestparam-together