경로 : hello.springmvc.basic.requestmappig
package hello.springmvc1.basic.requestmapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MappingController {
private Logger log = LoggerFactory.getLogger(getClass());
/**
* 기본 요청
* 둘다 허용 /hello-basic, /hello-basic/
* HTTP 메서드 모두 허용, GET,HEAD,POST,PUT,PATCH,DELETE
*/
@RequestMapping("/hello-basic")
public String helloBasic(){
log.info("helloBasic");
return "ok";
}
}
@RequestMapping("/hello-basic")
-hello-bsic
URL 호출이 오면 이 메서드가 실행 되도록 Mapping한다.
배열[]
로 제공하므로 다중 설정이 가능하다. {"/hello-basic","/hello-go"}
둘다 혀용 - 스프링 부트 3.0 이전
다음 두가지 요청은 다른 URL 이지만, 스프링은 다음 URL 요청들을 같은 요청으로 Mapping 한다.
매핑 : /hello-basic
URL 요청 : /hello-basic
, /hello-basic/
🤞 참고 )
스프링 부트 3.0 부터는 /hello-basic
, /hello-basic
는 서로 다른 URL 요청을 사용해야 한다.
기존에는 마지막에 있는 /
(slash)를 제거 했지만, 스프링 부트 3.0 부터는 마지막의 /
를 유지한다.
매핑 : /hello-basic
-> url 요청 : /hello-basic
매핑 : /hello-basic/
-> url 요청 : /hello-basic/
@RequestMapping
에 method
속성으로 HTTP 메서드를 지정하지 않으면 HTTP 메서드와 무관하게 호출 된다.
모두 허용 GET,HEAD,POST,PUT,PATCH,DELETE
/**
* method 특정 HTTP 메서드 요청만 허용
* GET, HEAD, POST, PUT , PATCH , DELETE
*/
@RequestMapping(value="/mapping-get-v1", method = RequestMethod.GET)
public String mappingGetV1(){
log.info("mappingGetV1");
return "ok";
}
만약 여기에 POST 요청을 하면 스프링 MVC는 HTTP 405 상태코드(Method Not Allowed)를 반환한다.
/**
* 편리한 축약 애노테이션 (코드보기)
* @GetMapping
* @PostMapping
* @PutMapping
* @DeleteMapping
* @PatchMapping
*/
@GetMapping(value="/mapping-get-v2")
public String mappingGetV2(){
log.info("mapping-get-v2");
return "ok";
}
HTTP 메서드를 축약한 애노테이션을 사용하는 것이 더 직관적이다.
코드를 보면 내부에 @RequestMapping
과 method
를 지정해서 사용하는 것을 확인할 수 있다.
/**
* PathVariable 사용
* 변수명이 같으면 생략 가능
* @PathVariable("userId") String userId -> @PathVariable userId
*/
@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String data){
log.info("mappingPath userId ={}" , data);
return "ok";
}
실행 : http://localhost:8080/mapping/userA
최근 HTTP API는 다음과 같이 리소스 경로에 식별자를 넣는 스타일을 선호한다.
/mapping/userA
/users/1
@RequestMapping
은 URL 경로를 템플릿화 할 수 있는데, @PathVariable
을 사용하면 매칭 되는 부분을 편리하게 조회할 수 있다.
@PathVariable
의 이름과 파라미터 이름이 같으면 생략할 수 있다.
/**
* 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
/**
* 파라미터로 차가 매핑
* params="mode",
* params="!mode",
* params="mode=debug",
* params="mode!=debug" (!=),
* params={"mode=debug","data=good"}
*/
@GetMapping(value="/mapping-param", params = "mode=debug")
public String mappingParam(){
log.info("mappingParam");
return "ok";
}
실행 : http://localhost:8080/mapping-param?mode=debug
특정 파라미터가 있거나 없는 조건을 추가할 수 있다. 잘 사용하지는 않는다
/**
* 특정 헤더로 추가 매핑
* headers="mode",
* headers="!mode"
* headers="mode=debug"
* header="mode!-debug" (!=)
*/
@GetMapping(value = "/mapping-header", headers = "mode=debug")
public String mappingHeader(){
log.info("mappingHeader");
return "ok";
}
파라미터 매핑과 비슷하지만, HTTP 헤더를 사용한다.
Postman으로 테스트 해야 함
/**
* Content-Type 헤더 기반 추가 매핑 Media Type
* consumes="application/json"
* consumes="!aplication/json"
* consumes="application/*"
* consumes="*/*"
* MediaType.APPLICATION_JSON_VALUE
*/
@PostMapping(value="/mapping-consume", consumes="application/json")
public String mappingConsumes(){
log.inf("mappingConsumes");
return "ok";
}
Postman으로 테스트 해야 한다.
HTTP 요청의 Content-Type 헤더를 기반으로 미디어 타입으로 매핑한다.
만약 맞지 않으면 HTTP 415 상태코드(Unsupported Media Type)을 반환한다.
ex) consumes
consumes = "text/plain"
consumes = {"text/plain","application/*"}
consumes = MediaType.TEXT_PLAIN_VALUE
/**
* Accept 헤더 기반 Media Type
* produces = "text/html"
* produces = "!text/html"
* produces = "text/*"
* produces = "*/*"
*/
@PostMapping(value = "/mapping-produce",produces = "text/html")
public String mappingProduces(){
log.info("mappingProduces");
return "ok";
}
HTTP 요청의 Accept 헤더를 기반으로 미디어 타입으로 매핑한다.
만약 맞지 않으면 HTTP 406 상태코드(Not Acceptable)을 반환 한다.
ex)
produces = "text/plain"
produces = {"text/plain","applicaiton/*"}
produces = MediaType.TEXT_PLAIN_VALUE
produces = "text/plain;charset=UTF-8"
회원 관리를 HTTP API로 만든다 생각하고 매핑을 어떻게 하는지 알아보자
(실제 데이터가 넘어가는 부분은 생략하고 URL 매핑만)
회원 목록 조회 : GET /users
회원 등록 : POST /users
회원 조회 : GET /users/{userId}
회원 수정 : PATCH /users/{userId}
회원 삭제 : DELETE /users/{userId}
경로 : hello.springmvc.basic.requestmapping
package hello.springmvc1.basic.requestmapping;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/mapping/users")
public class MappingClassController {
/**
* GET /mapping/users
*/
@GetMapping
public String users(){
return "get users";
}
/**
* POST /mapping/users
*/
@PostMapping
public String addUser(){
return "post user";
}
/**
* GET /mapping/users/{userId}
*/
@GetMapping("/{userId}")
public String findUser(@PathVariable String userId){
return "get userId " + userId;
}
/**
* PATCH /mapping/users/{userId}
*/
@PatchMapping("/{userId}")
public String updateUser(@PathVariable String userId){
return "update useId = " + userId;
}
/**
* DELETE /mapping/users/{userId}
*/
@DeleteMapping("/{userId}")
public String deleteUser(@PathVariable String userId){
return "delete userId =" + userId;
}
}
/mapping
:는 다른 예제들과 구분하기 위해 사용
@RequestMapping("/mapping/user")
Postman으로 테스트
매핑 방법을 이해했으니, 이제 HTTP 요청이 보내는 데이터들을 스프링 MVC로 어떻게 조회하는지 알아봄