코드 리팩토링하고 테스트코드 짜는데 자꾸 에러나서 찡얼거렸던 하루... 였는데 알고보니 내 잘못이었다 ㅎㅎ @PathVariable과 @ModelAttribute에 대해서 뭔가 알지 못했던 부분이 있었던 것이다.
URL의 값을 정의한 이름과 같은 이름의 인자랑 매핑시키고자 할 때 사용한다. 아래와 같이 사용할 수 있다.
public class TestController {
@GetMapping("/{name}")
public ResponseEntity<String> test(@PathVariable String name){
System.out.println(name);
return ResponseEntity.ok("OK");
}
}
GET으로 요청할 때 다음과 같다.
http://localhost:8080/jin
주의할 점
null이나 공백이 들어오는 경우에는 사용하면 안된다.
값에 .이 포함되어 있다면 그 뒤는 잘려서 들어온다.
물론, @RequestParam으로 값을 여러 개 받을 수 있긴 하다. 하지만, 파라미터를 다 적어주자니 코드가 지저분해질 것이다. 이럴 때 인자로 클래스를 받도록 하고 앞에 @ModelAttribute를 써줄 수 있다. 아래와 같이 말이다.
Dto.java
public class DTO {
String name;
String age;
...
// getter
// setter
}
TestController.java
@RestController
public class TestController {
@GetMapping("/")
public ResponseEntity<String> test(@ModelAttribute Dto dto){
System.out.println(dto.getName());
System.out.println(dto.getAge());
return ResponseEntity.ok("OK");
}
}
name과 age에 대한 값은 Dto 클래스의 setter를 통해 각 변수에 매핑된다. 따라서 @ModelAttribute를 사용하고 싶다면 Dto 클래스에 setter가 있어야 한다.
위의 사실까지는 알고 있었지만 URL을 뜯어본 것은 처음이었다.
(그래서 단위 테스트 하면서 오류를 맞이했다는...)
GET으로 요청할 때 다음과 같다.
http://localhost:8080?name=jin&age=23
@RequestParam으로 하나하나 작성했을 때와 같은 형태다.
여담
파일 다운로드 기능을 리팩토링 중이었다. 파일 명을 전달 받아야 하는 상황이었는데 돌아가는 것만 보고 Swagger로 URL을 뜯어보지 않은 것이 잘못이었다.
@RestController public class FileDownloadController { @GetMapping("/{name.+}") public ResponseEntity<String> test(@ModelAttribute FileDto dto){ ... } }
FileDto에는 파일 이름만 속성으로 들어있는 상태다. 이거 돌아가기는 잘 돌아가는데, URL이 말도 안되게 나와서 애먹었다...
결론
속성들을 전부 파라미터로 적어주고 @PathVariable을 써줄지 DTO 하나 만들어서 @ModelAttribute를 써줄지는 속성 개수에 따라, 본인 코딩 스타일에 따라 달라질 것 같다.