클라이언트에서 서버로 데이터를 전송하는 방법 중,
3. HTTP message body에 데이터를 직접 담아서 요청
하는 방법은 요청 파라미터와 다르게 @RequestParam, @ModelAttribute를 사용할 수 없다.
<HTTP 요청 메시지 - 단순 텍스트>
InputStream을 사용해서 직접 읽을 수 있다.
package hello.springmvc.basic.request;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
@Slf4j
@Controller
public class RequestBodyStringController {
@PostMapping("/request-body-string-v1")
public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
response.getWriter().write("ok");
}
@PostMapping("/request-body-string-v2")
public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException {
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
responseWriter.write("ok");
}
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) throws IOException {
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("ok");
}
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
log.info("messageBody={}", messageBody);
return "ok";
}
}
HttpEntity: HTTP header, body 정보를 편리하게 조회
- 메시지 바디 정보를 직접 조회
- HttpEntity는 응답에서도 사용 가능
- view 조회하지 않고 메시지 바디 정보를 직접 반환한다.
@RequestBody 로 HTTP 메시지 바디 정보를 편리하게 조회 가능.
헤더 정보가 필요하다면 HttpEntity나, @RequestHeader를 사용하면 된다.
요청 파라미터 vs HTTP 메시지 바디
* 요청 파라미터를 조회하는 기능: @RequestParam , @ModelAttribute
* HTTP 메시지 바디를 직접 조회하는 기능: @RequestBody
<HTTP 요청 메시지 - JSON>
package hello.springmvc.basic.request;
import com.fasterxml.jackson.databind.ObjectMapper;
import hello.springmvc.basic.HelloData;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Slf4j
@Controller
public class RequestBodyJsonController {
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");
}
@ResponseBody
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
log.info("messageBody={}", messageBody);
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
@ResponseBody
@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) {
HelloData data = httpEntity.getBody();
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
@ResponseBody
@PostMapping("/request-body-json-v4")
public HelloData requestBodyJsonV4(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
return data;
}
}
V1: 문자로 된 JSON 데이터를 Jackson 라이브러리인 objectMapper 를 사용해서 자바 객체로 변환한다.
V2: @RequestBody를 사용해 HTTP 메시지에서 데이터를 꺼내고 messageBody에 저장한다.
-> 문자로 변환하고 다시 json으로 변환하는 과정이 불편한다. @ModelAttribue처럼 한번에 객체로 변환할 수 없을까?
V3: @RequestBody HelloData data => @RequestBody에 직접 만든 객체를 지정할 수 있다.
HttpEntity, @RequestBody를 사용하면 HTTP 메시지 컨버터가 HTTP 메시지 바디의 내용을 문자나 객체 등으로 변환해준다.
V4: HttpEntity 사용
V5: @ResponseBody 를 사용해 해당 객체를 HTTP 메시지 바디에 직접 넣어줄 수 있다.
<HTTP 요청 메시지 - 정적 리소스, 뷰 템플릿>
스프링(서버)에서 응답 데이터를 만드는 방법은 크게 3가지.
1. 정적 리소스
- 아래 디렉토리에 있는 정적 리소스를 제공
- /static , /public , /resources ,/META-INF/resources
2. 뷰 템플릿 사용
- 기본 뷰 템플릿 경로: src/main/resources/templates
3. HTTP 메시지 사용
HTTP 응답 - HTTP API, 메시지 바디에 직접 입력
package hello.springmvc.basic.response;
import hello.springmvc.basic.HelloData;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.io.IOException;
@Slf4j
@Controller
public class ResponseBodyController {
@GetMapping("/response-body-string-v1")
public void responseBodyV1(HttpServletResponse response) throws IOException {
response.getWriter().write("ok");
}
@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("ok", HttpStatus.OK);
}
@ResponseBody
@GetMapping("/response-body-string-v3")
public String responseBodyV3() {
return "ok";
}
@GetMapping("/response-body-json-v1")
public ResponseEntity<HelloData> responseBodyJsonV1() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return new ResponseEntity<>(helloData, HttpStatus.OK);
}
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return helloData;
}
}
BodyV1: HttpServletResponse 객체를 통해서 HTTP 메시지 바디에 직접 `ok` 응답 메시지를 전달
BodyV2: ResponseEntity는 HttpEntity를 상속받은 객체. HTTP 응답 코드를 설정할 수 있다.
Bodyv3: @ResponseBody를 사용하면 view를 사용하지 않고 HTTP 메시지를 직접 입력할 수 있다.
JsonV1: ResponseEntity를 JSON 형식으로 변환되어 반환
JsonV2: @ResponseStatus(HttpStatus.OK) 애노테이션을 사용하면 응답 코드도 설정할 수 있다.
*@RestController
해당 컨트롤러에 모두 @ResponseBody가 적용된다. 따라서 뷰 템플릿을 사용하는 것이 아니라, HTTP 메시지 바디에 직접 데이터를 입력한다. Rest API(HTTP API)를 만들 때 사용하는 컨트롤러이다.
'공부 > Spring' 카테고리의 다른 글
[Spring MVC](9) 검증(Validation) (2) | 2024.01.28 |
---|---|
[Spring MVC](8) 웹 페이지 만들기 (0) | 2024.01.22 |
[Spring MVC](6) 기본 기능 - 요청 매핑, 요청 데이터 1 (0) | 2024.01.22 |
[Spring MVC](5) 스프링 MVC - 구조 이해 (1) | 2024.01.22 |
[Spring MVC](4) 프레임워크 만들기 v4,5 (0) | 2024.01.22 |