본 내용은 온라인 강의 사이트 인프런의 김영한 님의 강의 내용이 포함되어 있습니다.
'스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술'
@RequestMapping
클라이언트 요청에 정보를 어떤 Controller가 처리할지를 매핑하기 위한 어노테이션이다.
@RequestMapping에 URL을 포함하여 해당 Controller 클래스에 명시하여 사용한다.
웹 브라우저에서 해당 URL이 호출되면 Controller 내부의 메서드가 호출된다.
@RequestMapping("/members")
public class MemberController {
...
}
@Controller
스프링이 자동으로 스프링 빈으로 등록한다. @Controller 어노테이션 내부에 @Component 어노테이션이 포함되어 있어 컴포넌트 스캔의 대싱이 되기 때문이다.
Spring MVC에서 어노테이션 기반 컨트롤러로 인식하게 된다.
@Controller
public class MemberController {
...
}
@RestController
스프링이 자동으로 스프링 빈으로 등록한다. @RestController 어노테이션 내부에 @Component 어노테이션이 포함되어 있어 컴포넌트 스캔의 대싱이 되기 때문이다.
Spring MVC에서 어노테이션 기반 컨트롤러로 인식하게 된다.
@RestController
@RequestMapping("/members")
public class MemberController {
}
@RestController는 @Controller과 차이점이 있다.
- @Controller는 반환 값이 String이면 뷰 이름으로 인식된다. 따라서 뷰를 찾고 뷰가 랜더링 된다.
- @RestController는 반환 값으로 뷰를 찾는 것이 아닌, HTTP 메시지 바디에 바로 입력한다. 따라서 실행 결과로 ok 메시지를 받을 수 있다. @ResponseBody와 관련이 있다.
@RequestMapping과 @Controller
스프링 빈 중에서 @RequestMapping이 있으면, 핸들러 매핑 조회할 때, RequestMappingHandlerMapping이 실행된다.
RequestMappingHandlerMapping은 스프링 빈 중에서 @RequestMapping 또는 @Controller가 클래스 레벨에 붙어 있는 경우에 매핑 정보로 인식하게 된다.
@Controller
@RequestMapping("/members")
public class MemberController {
}
@Componet를 통해 스프링 빈으로 등록하고, @RequestMapping을 통해 매핑 정보로 인식하게 된다.
@Controller 어노테이션 내부에는 @Component가 포함되어 있다.
@RequestMapping과 HTTP 메서드
@RequestMapping은 URL만 매칭 하는 것이 아닌, HTTP 메서드도 함께 구분할 수 있다.
예를 들어, URL이 /new-form이고, HTTP 메서드가 GET인 경우를 모두 만족해야 한다면 다음과 같이 작성해야 한다.
@RequestMapping(value = "/new-form", method = RequestMethod.GET)
public String newForm() {
}
@RequestMapping에 method 속성으로 HTTP 메서드를 지정하지 않으면, HTTP 메서드와 무관하게 GET, HEAD, POST, PUT, PATCH, DELETE 등 모든 HTTP 메서드 호출이 가능하다.
@RequestMapping(value = "/hello-basic", method = RequestMethod.GET)
@RestController
public class MappingController {
@RequestMapping(value = "/hello-basic", method = RequestMethod.GET)
public String helloBasic() {
return "ok";
}
}
만약 위 코드를 실행한 뒤, POST 요청을 하게 되면 스프링 MVC는 HTTP 405 상태 코드(Method Not Allowed)를 반환한다.
Postman으로 테스트
편리한 매핑 어노테이션
하지만, @RequestMapping 어노테이션을 각각의 매핑 메서드로 제한하는 어노테이션으로 사용하여 편리하게 이용할 수 있다.
@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
@GetMapping("/mapping-get")
public String mappingGet() {
return "ok";
}
@PostMapping("/mapping-post")
public String mappingPost() {
return "ok";
}
@PutMapping("/mapping-put")
public String mappingPut() {
return "ok";
}
@DeleteMapping("/mapping-delete")
public String mappingDelete() {
return "ok";
}
@PatchMapping("/mapping-patch")
public String mappingPatch() {
return "ok";
}
@RequestMapping 다중 경로
또한, @RequestMapping은 url을 배열로 사용하여 다중 설정이 가능하다.
@RestController
public class MappingController {
private Logger log = LoggerFactory.getLogger(getClass());
// 다중 설정
@RequestMapping({"/hello-basic", "/hello-go"})
public String helloBasic() {
log.info("helloBasic");
return "ok";
}
}
위 코드의 경우 실행을 하게 되면 웹 브라우저에서 아래와 같이 두 가지 경로에서 확인이 가능하다.
http://localhost:8080/hello-basic
http://localhost:8080/hello-go
PathVariable(경로 변수) 사용
@RequsetMapping과 @GetMapping 등에는 method를 변수로 지정하여 사용이 가능하다.
@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String id) {
log.info("mappingPath userId={}", id);
return "ok";
}
만약, 변수명이 경로명과 같으면 @PathVariable의 속성을 생략할 수 있다.
@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable String userId) {
log.info("mappingPath userId={}", userId);
return "ok";
}
http://localhost:8080/mapping/userA와 같이 경로 변수에 해당하는 경로에 변수에 알맞은 값을 입력하여 요청을 보낼 수 있다.
// 출력
2022-10-27 22:07:27.286 INFO 22228 --- [nio-8080-exec-2] h.s.b.requestmapping.MappingController : mappingPath userId=userA
Postman을 통해 테스트가 가능하다.
PathVariable(경로 변수) 다중 매핑
@GetMapping("/mapping/users/{userId}/orders/{orderId}")
public String mappingPath(@PathVariable String userId, @PathVariable Long orderId) {
log.info("mappingPath userId={}, orderId={}", userId, orderId);
return "ok";
}
위 경우 http://localhost:8080/mapping/users/userA/orders/100와 같이 경로 변수를 다중으로 사용이 가능하다.
// 출력
2022-10-27 22:14:17.188 INFO 15756 --- [nio-8080-exec-3] h.s.b.requestmapping.MappingController : mappingPath userId=userA, orderId=100
특정 파라미터 조건 매핑
@GetMapping(value = "/mapping-param", params = "mode=debug")
public String mappingParam() {
log.info("mappingParam");
return "ok";
}
위 코드와 같이 매핑 어노테이션 속성에 params =을 추가하여 특정 조건에 대한 매핑을 수행할 수 있다.
- params = "mode=debug" : 파라미터에 mode=debug가 존재해야 호출이 된다.
- 즉, 호출을 하기 위해서는 http://localhost:8080/mapping-param?mode=debug로 접속해야 한다.
- http://localhost:8080/mapping-param로는 접속이 불가능하다.
- params에는 “!mode”, “mode!=debug”, {”mode=debug”, “data=good”} 등과 같이 사용할 수 있다.
- 하지만 실제로 사용하는 일은 거의 없다.
특정 헤더 조건 매핑
@GetMapping(value = "/mapping-header", headers = "mode=debug")
public String mappingHeader() {
log.info("mappingHeader");
return "ok";
}
위 코드와 같이 매핑 어노테이션 속성에 headers =을 추가하여 헤더 조건에 대한 매핑을 수행할 수 있다.
http://localhost:8080/mapping-header에 그냥 접속하면 404 상태 코드를 반환한다.
해당 경로에 접속하기 위해서는 아래 header 정보에 mode를 추가하여 값으로 debug로 지정해주어야 접속이 가능해진다.
특정 헤더 조건 역시, headers에는 “mode”, “!mode”, “mode≠debug 등과 같이 여러 방식의 조건을 사용할 수 있다.
미디어 타입 조건 매핑
consume
consumes를 통해 HTTP 요청 시 미디어 타입 조건도 매핑을 할 수 있다.
Content-Type에 따라 분리하여 매핑할 수 있다.
@PostMapping(value = "/mapping-consume", consumes = "application/json")
public String mappingConsumes() {
log.info("mappingConsumes");
return "ok";
}
위 코드의 경우 헤더의 Content-Type이 application/json인 경우에만 호출이 가능하다.
아래 이미지와 같이 헤더의 Content-Type이 조건에 맞지 않는 경우 415 상태 코드를 반환한다.
아래와 같이 Content-Type이 application/json인 경우에만 정상적으로 호출된다.
Accept, produce
헤더의 Accept 헤더를 기반의 미디어 타입으로 매핑한다.
@PostMapping(value = "/mapping-produce", produces = "text/html")
public String mappingProduces() {
log.info("mappingProduces");
return "ok";
}
만약, Accept 헤더가 일치하지 않으면 406 상태 코드를 반환한다.
다음과 같이 Accept가 text/html인 경우에 정상적으로 반환한다.
@RequestParam
스프링은 HTTP 요청 파라미터를 @RequestParam으로 받을 수 있다.
만약 요청 파라미터에 username과 age가 있다고 가정한다.
예전 방식
@RequestMapping("/save")
public ModelAndView save(HttpServletRequest request, HttpServletResponse response) {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
...
}
@RequestParam 사용
@PostMapping("/save")
public String save(@RequestParam("username") String username, @RequestParam("age") int age, Model model) {
...
}
HttpServletRequest과 HttpServletResponse을 파라미터로 받아 요청을 변환하고, ModelAndView로 반환하기까지의 불편한 로직이 상당 부분 해소되었다.
또한, Model 파라미터를 통해 내부 로직에 편의 기능을 제공받을 수 있다.
'프레임워크(Framework) > Spring' 카테고리의 다른 글
[Spring MVC] 스프링 MVC 뷰 리졸버(View Resolver) (0) | 2022.11.13 |
---|---|
[Spring MVC] 스프링 MVC 핸들러 매핑과 핸들러 어댑터 (0) | 2022.11.12 |
[Spring MVC] 스프링 MVC란 무엇인가? - 스프링 MVC 구조 이해 (0) | 2022.11.10 |
[Spring] 스프링 AOP 포인트컷(Pointcut) 표현식 정리 (0) | 2022.11.09 |
[Spring] AOP 용어 및 개념 정리 (0) | 2022.11.08 |