package hello.springmvc.basic;
import lombok.Data;
@Data // @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor 적용
public class HelloData {
private String username;
private int age;
}
실제 개발과정에 있어서는 다음과 같은 객체를 이용하는 경우가 많다.
보통 다음과 같은 과정을 통해 객체를 활용하고는 할텐데
이때 스프링 MVC는 이런 객체 활용에 있어 용이한 기능을 제공한다.
다음 코드를 자동화해준다고 생각하자
@RequestParam String username;
@RequestParam int age;
HelloData data = new HelloData();
data.setUsername(username);
data.setAge(age);
@ModelAttribute 애노테이션의 기능을 알아보겠다
다음 코드를 보자
package hello.springmvc.basic.request;
import hello.springmvc.basic.HelloData;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j
@Controller
public class RequestParamController {
// JSON식 Response 생성법
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@RequestParam String username, @RequestParam int age){
HelloData helloData = new HelloData();
helloData.setUsername(username);
helloData.setAge(age);
log.info("helloData={}", helloData.toString());
// 그냥 helloData하면 toString으로 출력됨.
return "ok";
}
@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV2(@ModelAttribute HelloData helloData){
//HelloData helloData = new HelloData();
//helloData.setUsername(username);
//helloData.setAge(age);
log.info("helloData={}", helloData.toString());
// 그냥 helloData하면 toString으로 출력됨.
return "ok";
}
@ResponseBody
@RequestMapping("/model-attribute-v3")
public String modelAttributeV3(HelloData helloData){
//HelloData helloData = new HelloData();
//helloData.setUsername(username);
//helloData.setAge(age);
log.info("helloData={}", helloData.toString());
// 그냥 helloData하면 toString으로 출력됨.
return "ok";
}
}
modelAttributeV1을 보면, 메서드에 HelloData 타입의 파라미터를 주고, @ModelAttribute 애노테이션만 적용해줬는데도
위에 일일히 객체를 생성하고 setter를 적용해줘야했던것과는 다르게, 요청 파라미터의 값이 모두 설정되어있다.
@ModelAttribute는 다음과 같은 과정을 자동화한다.
1. HelloData 객체를 생성
2. RequestParameter의 이름으로 HelloData 객체의 프로퍼티(setter,getter)를 찾는다.
그리고 해당 프로퍼티의 setter를 호출해서 파라미터의 값을 바인딩한다.
age=abc처럼 숫자가 들어가야 할 곳에 문자를 넣으면 BindException이 발생하는데 이는 검증부분에서 다룬다.
modelAttributeV2는 애노테이션을 생략해도 적용되는 것을 보여준다.
다만, @RequestParam도 생략이 가능하기 때문에 Clarification이 필요하다.
스프링은 애노테이션 생략시 다음과 같은 기준으로 적용한다
1) String, int, Integer와 같은 단순 타입 = @RequestParam
2) 나머지 객체 타입(userdefined) = @ModelAttribute(argument resolver로 지정해둔 타입 외)
HTTP 요청 메세지 - 단순 텍스트
HTTP 메세지 바디에 데이터를 직접 담아서 요청할 때,
JSON, XML, 단순 텍스트가 오고 갈 수 있는데 데이터 형식은 주로 JSON을 사용한다 했다.
요청 파라미터와 다르게 HTTP 바디를 통해 메세지가 직접 넘어오는 경우
@RequestParam이나 @ModelAttribute를 사용할 수 없다.
package hello.springmvc.basic.request;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.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;
@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){
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("ok");
}
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody){
log.info("messageBody = {}", messageBody);
return "ok";
}
}
1. requestBodyString
- Servlet에서 HTTP Body의 내용을 request의 getInputStream으로 파싱한 것과 같다.
이때 파싱을 위해 StreamUtils.copyToString을 사용해야하며 두번째 파라미터로 StandardCharsets.UTF-8을 넘겨주어야 한다는 것을 잊지 말자.
2. requestBodyStringV2
스프링 MVC는 다음 파라미터를 지원한다
- InputStream(Reader) : HTTP 요청 메세지 바디의 내용을 직접 조회
- OutputStream(Writer) : HTTP 응답 메세지의 바디에 직접 결과 출력
3. requestBodyStringV3
HttpEntity: HTTP header, Body 정보를 편리하게 조회함 -> HTTP 메세지를 스펙화 한 객체
요청 파라미터를 조회하는 기능과 관계 없음, @RequestParam, @ModelAttribute와 관계 X
Get의 쿼리스트링 Form Post, content-type : www-x-urlencoded외에는 직접 데이터 꺼내야 함.
HttpEntity는 응답에도 사용 가능
-> 메세지 바디 정보 직접 반환
-> 헤더 정보 포함 가능
-> view 조회 X
HttpEntity를 상속 받은 다음 객체들도 같은 기능을 제공한다
-> RequestEntity : HttpMethod, url 정보가 추가 / 요청에서 사용한다
-> ResponseEntity : Http 상태 코드 설정 가능, 응답에서 사용
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED)
4. requestBodyStringV4
@RequestBody를 사용하면 HTTP 메세지 바디 정보를 편리하게 조회함.
헤더 정보가 필요하다면, HttpEntity를 사용하거나 @RequestHeader를 사용하면 된다.
메세지 바디를 직접 조회하는 기능은 요청 파라미터를 조회하는 @RequestParam, @ModelAttribute와는 상관 없다
요청 파라미터 vs HTTP 메세지 바디
- > 요청 파라미터를 조회하는 기능 : @RequestParam, @ModelAttribute
- > HTTP 메세지 바디를 직접 조회하는 기능 : @RequestBody
@ResponseBody를 사용하면 응답 결과를 HTTP 바디에 직접 담아서 전달할 수 있는데, 이때도 뷰 사용 X
'스프링 공부 (인프런 김영한 선생님) > 스프링 MVC 1편' 카테고리의 다른 글
[스프링 웹 MVC 1편] 24. HTTP 응답 - 정적 리소스, 뷰 템플릿 (0) | 2023.06.04 |
---|---|
[스프링 웹 MVC 1편] 23. HTTP 요청 파라미터 (JSON) (0) | 2023.06.03 |
[스프링 웹 MVC 1편] 21. 스프링 MVC - 기본기능 (기본/헤더/쿼리파라미터/ HTML Form 조회) (1) | 2023.06.03 |
[스프링 웹 MVC 1편] 20. 스프링 MVC - 기본기능 (요청매핑) (0) | 2023.06.03 |
[스프링 웹 MVC 1편] 19. 스프링 MVC - 기본 기능 (로깅) (0) | 2023.06.01 |