스프링 MVC: 요청 메시지(몰랐던것 중심)

RisingJade의 개발기록·2022년 3월 3일
0

SPRING MVC

목록 보기
4/6

HTTP 요청 메시지 - 단순 텍스트

content-body를 통해 단순 텍스트를 얻는 방법에는 여러가지가 있다 .

  • request.getInputStream이용

@PostMapping("/request-body-string-v1")
    public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        //stream은 bytecode이니 string으로 바꿀때는 어떤 인코딩으로 바꿀건지 설정해주어야 한다. 지정 안할경우 default값이 설정된다.
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

        log.info("message-body={}", messageBody);

        response.getWriter().write("ok");
    }

위의 방식이 너무 지저분하다면 inputstream만 미리 떼와서 쓸수도 있다.

  • 스프링 MVC는 다음 파라미터를 지원한다.
    InputStream(Reader): HTTP 요청 메시지 바디의 내용을 직접 조회
    OutputStream(Writer): HTTP 응답 메시지의 바디에 직접 결과 출력
@PostMapping("/request-body-string-v2")//input stream과 writer를 그냥 받아서 바로 쓴다.
    public void requestBodyStringV2(InputStream inputStream, Writer responseWriter)
            throws IOException {
        String messageBody = StreamUtils.copyToString(inputStream,
                StandardCharsets.UTF_8);
        log.info("messageBody={}", messageBody);
        responseWriter.write("ok");
    }
  • HttpEntity이용

 @PostMapping("/request-body-string-v3")
    public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
        String messageBody = httpEntity.getBody();
        log.info("messageBody={}", messageBody);
        return new HttpEntity<>("ok");
    }
  • HttpEntity: HTTP header, body 정보를 편리하게 조회
    • 메시지 바디 정보를 직접 조회
    • 요청 파라미터를 조회하는 기능과 관계 없음 @RequestParam X, @ModelAttribute X
  • HttpEntity는 응답에도 사용 가능
    • 메시지 바디 정보 직접 반환
    • 헤더 정보 포함 가능
    • view 조회X (@ResponseBody처럼 사용)

HttpEntity 를 상속받은 다음 객체들도 같은 기능을 제공한다.

  • RequestEntity
    • HttpMethod, url 정보가 추가, 요청에서 사용
  • ResponseEntity
    • HTTP 상태 코드 설정 가능, 응답에서 사용
    • return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED)

TIP:
스프링MVC 내부적으로 HTTP메시지 바디를 읽어서 문자나 객체로 변환해서 전달하는데 이때 스프링은 HTTP 메시지 컨버터라는 기능을 사용하는 것이다.

  • @RequestBody

    @RequestBody 를 사용하면 HTTP 메시지 바디 정보를 편리하게 조회할 수 있다. 참고로 헤더 정보가 필요하다면 HttpEntity를 사용하거나 @RequestHeader를 사용하면 된다. 이렇게 메시지 바디를 직접 조회하는 기능은 요청 파라미터를 조회하는 @RequestParam, @ModelAttribute 와는 전혀 관계가 없다.
    @ResponseBody
    @PostMapping("/request-body-string-v4")
    public String requestBodyStringV4(@RequestBody String messageBody) {
        log.info("messageBody={}", messageBody);
        return "ok";
    }

HTTP 요청 메시지 - JSON

기본형은 아래와 같다.
1. HttpServletRequest를 사용해서 직접 HTTP 메시지 바디에서 데이터를 읽어와서, 문자로 변환한다.
2. 문자로 된 JSON 데이터를 Jackson 라이브러리인 objectMapper 를 사용해서 자바 객체로 변환한다.

private ObjectMapper objectMapper = new ObjectMapper();

    @PostMapping("/request-body-json-v1")
    public void requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

        log.info("messageBody={}", messageBody);
        HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
        log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());

        response.getWriter().write("ok");
    }
  • @RequestBody

    딱봐도 위의 방법은 너무 복잡하다. Spring에선 @RequestBody를 지원하는데 바디의 타입이 JSON일 경우 HTTP 메시지 컨버터가 자동으로 ObjectMapper를 호출해서 매개변수로 둔 객체에 맴버변수가 이름이 같은경우에 한해서 넣어 준다.
    @ResponseBody
    @PostMapping("/request-body-json-v3")
    public String requestBodyJsonV2(@RequestBody HelloData helloData) throws IOException {
        log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
        return "ok";
    }

주의!
1. @RequestBody는 생략 불가능!
@RequestBody 를 생략하면 @ModelAttribute가 적용되어버린다.

2. HTTP 요청시에 content-type이 application/json인지 꼭! 확인해야 한다.
그래야 JSON을 처리할 수있는 HTTP 메시지 컨버터가 실행된다.

  • HttpEntity<>

    일반 텍스트에서도 HttpEntity<String>을 썼듯이 이번에는 HttpEntity<HelloData>라고 쓰면된다.
    @ResponseBody
    @PostMapping("/request-body-json-v4")
    public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) throws IOException {
        HelloData helloData = httpEntity.getBody();// <>제네릭 선언이 되어있어서 getBody를 하면 HelloData타입으로 받아짐
        log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
        return "ok";
    }

Tip.
단순히 받을때만 @RequestBody를 통해 JSON 타입을 받는것이 아니라 @ResponseBody를 통해서 응답을 JSON으로 반환 할 수 있다. (당연히 HTTP 메시지 컨버터가 해준다.)

profile
언제나 감사하며 살자!

0개의 댓글