@RequestParam, @ModelAttribute
클라이언트에서 서버로 요청 데이터를 전달할 때 3가지 방법이 있다.
1. GET 메시지 바디 없이, URL의 쿼리파라미터에 데이터를 포함해서 전달하는 방식
보통 검색, 필터, 페이징 등에서 많이 사용된다.
http://localhost:8080/request-param-v1?username=hello&age=20
2. POST HTML Form으로 전달하는 방식
POST /request-param ...
content-type: application/x-www-form-urlencoded
username=hello&age=20
3. HTTP message body에 데이터를 직접 담아서 요청하는 방식
HTTP API에서 주로 사용되며, JSON / XML / TEXT가 있다. 이중 데이터는 주로 JSON 사용
이중에서 해당 글은 1, 2를 다룬다.
테스트하기에 앞서 테스트용 HTML Form을 만든다.
리소스는 /resources/static 아래에 두면 스프링 부트가 자동으로 인식한다.
http://localhost:8080/basic/hello-form.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/request-param-v1" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
</body>
</html>
HttpServletRequest의 request.getParameter()를 사용하면 GET 쿼리 파라미터, POST HTML Form 전송한 데이터을 조회할 수 있다. 2가지 모두 형식이 같으므로 구분없이 조회할 수 있다. 이것을 요청파라미터(request parameter) 조회라 한다.
HttpServletRequest가 제공하는 방식으로 요청 파라미터를 조회한다.
http://localhost:8080/request-param-v1?username=hello&age=20
@RequestMapping("/request-param-v1")
public void requestParamV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
log.info("username = {}, age = {}", username, age);
response.getWriter().write("WOW");
}
스프링이 제공하는 @RequestParam을 사용하면 요청 파라미터를 편리하게 조회할 수 있다.
@ResponseBody //REST
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam("username") String memberName,
@RequestParam("age") String memberAge) {
log.info("username = {}, age = {}", memberName, memberAge);
return "WOW";
}
@RequestParam은 파라미터 이름으로 바인딩된다.
@ResponseBody는 View 조회를 무시하고, HTTP message body에 직접 해당 내용을 입력한다.
HTTP 파라미터 이름과 변수 이름이 같으면 괄호를 생략할 수 있다.
@RequestParam.required 통해 파라미터의 필수 여부를 체크할 수 있다. 기본값은 파라미터 필수인 true이다.
int에 null 입력하면 500 예외가 발생한다. 따라서 null을 받을 수 있는 Integer를 사용한다.
@ResponseBody
@RequestMapping("/request-param-required")
public String requestParamRequired(@RequestParam(required = true) String username,
@RequestParam(required = false) Integer age) {
log.info("username = {}, age = {}", username, age);
return "WOW";
}
빈 값으로 통과
//통과
http://localhost:8080/request-param-required?username=wow
//빈값으로 통과
http://localhost:8080/request-param-required?username=&age=20
//400예외 발생
http://localhost:8080/request-param-required?age=20
파라미터에 값이 없는 경우 defaultValue를 사용하면 기본 값을 적용할 ㅜㅅ 있다.
따라서 기본값이 있기 때문에 required는 의미가 없다.
@ResponseBody
@RequestMapping("/request-param-default")
public String requestParamDefault(@RequestParam(required = true, defaultValue = "guest") String username,
@RequestParam(required = false, defaultValue = "1") int age) {
log.info("username = {}, age = {}", username, age);
return "WOW";
}
개발을 하다보면 요청 파라미터를 받아서 객체를 만들고 그 객체에 값을 넣어주어야 한다.
이 과정을 스프링에선 자동화 해주는 @ModelAttribute 기능을 제공한다.
우선 요청 파라미터를 바인딩 받을 객체 생성한다.
@Data
public class HelloData {
private String username;
private int age;
}
여기서 롬복의 @Data는 @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 자동으로 적용해준다.
HelloData 객체가 생성되고 요청 파라미터의 값이 모두 들어가 있다.
@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV21(@ModelAttribute HelloData helloData) {
log.info("username = {}, age = {}", helloData.getUsername(), helloData.getAge());
log.info("helloData = {}", helloData);
return "OK";
}
@ModelAttribute가 있으면 다음과 같이 실행된다.
1. HelloData 객체 생성
2. 요청 파라미터의 이름으로 HelloData 객체의 프로퍼티를 찾는다.
3. 해당 프로퍼티의 Setter를 호출해서 파라미터의 값을 입력(바인딩)한다.
🔗 강의 링크