@RequestMapping
📌클라이언트의 요청 URL과 이를 처리할 컨트롤러의 클래스나 메서드를 매핑하는 데 사용됩니다.
- 특정 URL로 Request를 보내면 들어온 요청을 Controller 내부의 특정 Method와 Mapping 하기 위해 사용한다.
- Client로부터 요청이 왔을 때 어떤 Controller가 호출될지 Mapping하는것은 단순히 URL로 Mapping 하는것이 아니라 여러가지 요소(URL, Method 등)를 조합하여 Mapping한다.
@RequestMapping과 Handler Adapter의 차이
@RequestMapping | Handler Adapter |
HTTP 요청과 컨트롤러 메서드를 연결하는 어노테이션 | DispatcherServlet과 핸들러(컨트롤러) 사이를 연결하는 구현체 |
메타데이터로써 동작 (어떤 요청이 어떤 메서드와 연결될지) | 요청을 실행 가능한 형태로 변환하고 핸들러 실행. |
개발자가 컨트롤러 메서드에 명시적으로 사용. | Spring 내부에서 동작하며, 개발자가 직접 호출하지 않음. |
주요 기능
- 요청 URL과 매핑: 특정 URL 경로로 들어오는 HTTP 요청을 처리할 메서드나 클래스와 연결.
- HTTP 메서드 지정: GET, POST, PUT, DELETE 등 특정 HTTP 메서드에만 반응하도록 설정.
- 요청 조건 추가: 요청 헤더, 파라미터 등 특정 조건에 맞는 요청만 처리 가능.
요청 종류
- @RequestMapping
- Spring Boot 3.0 버전 이하
- URL path /example, /example**/** 모두 허용(Mapping)한다.
- Spring Boot 3.0 버전 이상(현재 버전)
- URL path /example 만 허용(Mapping)한다.
- 속성값들을 설정할 때 배열 형태로 다중 설정이 가능하다
- HTTP Method POST, GET, PUT, PATCH, DELETE, HEAD 모두 허용한다
- method 속성으로 HTTP 메서드를 지정하면 지정된것만 허용한다.
- Spring Boot 3.0 버전 이하
package com.example.springbasicannotation.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
// 응답 데이터를 반환한다.
@RestController
public class RequestMappingController {
// HTTP Method 는 GET만 허용한다.
@RequestMapping(value = "/v1", method = RequestMethod.GET)
public String exampleV1() {
// logic
return "this is sparta!";
}
}
- 만약, 속성으로 설정된 HTTP Method로 요청이 오지 않는다면?
- localhost:8080/v1 + POST, PUT, PATCH, DELETE 의 경우
- HTTP 응답 상태코드 405(Client측 에러), Method Not Allowed Exception 반환
- @GetMapping
- Target(ElementType.METHOD) Method Level에 해당 어노테이션을 적용한다 라는 의미
- 내부적으로 @RequestMapping(method = RequestMethod.GET) 을 사용하고 있다.
코드예시
// Post, GET, Put, Patch, Delete 모두 가능
@GetMapping(value = "/v2")
public String exampleV2() {
// logic
return "this is sparta!";
}
- Spring이 제공하는 Annotation들의 내부에 다 선언되어 있다.
- 대부분의 필요한 기능들이 이미 만들어져 있다. 사용 하면된다.
- @RequestMapping 보다는 직관적이고 축약된 @GetMapping, @PostMapping 형식을 일반적으로 사용한다.
- 실행 결과
- @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
- 모두 위의 @GetMapping과 같은 구조를 가지고 있다.
- @RequestMapping는 언제 사용하는가?
- @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping의 Target은 Method Level 이다.
- 반면에 @RequestMapping의 Target은 class, method 레벨에 적용이 가능하다.
- Restful API의 계층 구조
메소드 레벨(Method Level)이란? 메소드 레벨은 클래스의 메서드에 적용할 수 있는 어노테이션의 사용 범위를 의미합니다.
즉, 메서드 레벨의 어노테이션은 클래스 내부의 특정 메서드에만 적용되어 동작합니다. |
ex) users/{userId}, category/{categoryId}/product/{productId}
- prefix로 선언할 URL을 class 레벨에 적용하는 것에 주로 사용된다.
@RequestMapping("/prefix")
@RestController
public class RequestMappingController {
// Post, GET, Put, Patch, Delete 모두 가능
@GetMapping(value = "/v3")
public String exampleV3() {
// logic
return "this is sparta!";
}
}
@PathVariable
📌 URL 경로에 포함된 변수를 메서드의 매개변수로 전달하기 위해 사용됩니다. 주로 RESTful 웹 서비스에서 동적인 요청 처리를 위해 사용됩니다.
- HTTP 특성 중 하나인 비연결성을 극복하여 데이터를 전달하기 위한 방법 중 하나이다. URL로 전달된 값을 파라미터로 받아오는 역할을 수행한다.
동작 원리
- URL 경로에 **변수(placeholder)**를 정의하고, 해당 값을 컨트롤러 메서드의 매개변수로 전달합니다.
- @PathVariable은 요청 경로에서 변수 값을 추출하여 메서드 파라미터에 바인딩합니다.
- @PathVariable
- 경로 변수를 중괄호에 둘러싸인 값으로 사용할 수 있다.
- 기본적으로 @PathVariable로 설정된 경로 변수는 반드시 값을 가져야 하며 값이 없으면 응답 상태코드 404 Not Found Error가 발생한다.
- 최근 Restful API를 설계하는 것이 API의 기준이 되며 해당 어노테이션의 사용 빈도가 높아졌다.
Restful API를 설계하게 되면 URL path 만으로 어떤 Resource을 사용하는지, HTTP Method 만으로 어떤 기능이 동작되는지 쉽게 알아볼 수 있다.
Restful API
https://restfulapi.net/resource-naming/
- Create - POST
- Read - GET
- Update - PUT, PATCH
- Delete - DELETE
- Restful API 설계 예시
- postId글의 comment 댓글 작성
- POST + posts/{postId}/comments
- postId글의 comment 댓글 전체 조회
- GET + posts/{postId}/comments
- postId글의 commentId 댓글 단 건 조회
- GET + posts/{postId}/comments/{commentId}
- postId글의 commentId 댓글 수정
- PUT + posts/{postId}/comments/{commentId}
- postId글의 commentId 댓글 삭제
- DELETE + posts/{postId}/comments/{commentId}
- postId글의 comment 댓글 작성
- @PathVariable 규칙
- 파라미터 변수명과 PathVariable 변수명이 같으면 속성 값 생략 가능
@RequestMapping("/posts")
@RestController
public class PathVariableController {
// postId로 된 post 단건 조회
@GetMapping("/{postId}")
public String pathVariableV1(@PathVariable("postId") Long data) {
// logic
String result = "PathvariableV1 결과입니다 : " + data;
return result;
}
}
@RequestMapping("/posts")
@RestController
public class PathVariableController {
// 변수명과 같다면 속성값 생략가능
@GetMapping("/{postId}")
public String pathVariableV2(@PathVariable Long postId) {
// logic
String result = "PathvariableV2 결과입니다 : " + postId;
return result;
}
}
2. @PathVariable 다중 사용 가능
@RestController
public class PathVariableController {
@GetMapping("/{postId}/comments/{commentId}")
public String pathVariableV3(
@PathVariable Long postId,
@PathVariable Long commentId
) {
// logic
String result = "PathvariableV3 결과입니다 postId : " + postId + "commentsId : " + commentId;
return result;
}
}
@RequestMapping("/posts/{postId}")
@RestController
public class PathVariableController {
@GetMapping("/comments/{commentId}")
public String pathVariableV4(
@PathVariable Long postId,
@PathVariable Long commentId
) {
// logic
String result = "PathvariableV4 결과입니다 postId : " + postId + "commentsId : " + commentId;
return result;
}
}
특정 파라미터 매핑
📌 속성 설정을 통하여 특정 헤더, 특정 파라미터와 Mapping 할 수 있다.
Parameter 추가 매핑
- 특정 파라미터와 매핑하는 방법
package com.example.springbasicannotation.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ParameterController {
// parms 속성값 추가
@GetMapping(value = "/users", params = "gender=man")
public String params() {
// logic
String result = "params API가 호출 되었습니다.";
return result;
}
}
- 실제 URL GET http://localhost:8080/users**?gender=man** 파라미터가 있어야 호출된다.
- 실행결과
- 파라미터가 없다면?
- 속성 작성 규칙
- params = "gender"
- params의 key값은 커스텀이 가능하다
- value는 없어도 된다.
- params = "!gender"
- gender가 없어야 한다.
- params = "gender=man"
- gender=man 이어야 한다.
- params = "gender!=man"
- params의 value값이 man가 아니여야 한다.
- params = {"gender=man", "gender=woman"}
- 배열로 속성 값을 여러 개 설정이 가능하다.
- params = "gender"
특정 Header 매핑
- 특정 Header와 매핑하는 방법
@RestController
public class ParameterController {
// headers 속성값 추가
@PostMapping(value = "/users", headers = "Content-Type=application/json")
public String headers() {
// logic
String result = "headers API가 호출 되었습니다.";
return result;
}
}
- Postman → Body → raw → JSON
- Postman → Headers → hidden
- HTTP Header를 사용하기 때문에 Postman으로 테스트 해야 한다.
ex) key=Content-Type / value=application/json
- 실행결과
- 속성 작성 규칙은 위 params 속성 값의 규칙과 같다.
MediaType 매핑, consume(수용)
- HTTP Header Content-Type(요청)과 매핑 된다.
@RestController
public class ParameterController {
// consumes 속성값 추가
@PostMapping(value = "/users", consumes = "application/json") // MediaType.APPLICATION_JSON_VALUE
public String consumes() {
// logic
String result = "consumes API가 호출 되었습니다.";
return result;
}
}
- consumes 속성 value값으로는 이미 Spring에서 제공되는 Enum인
- MediaType.APPLICATION_JSON_VALUE 형태로 사용한다.
- Postman → Body → raw → JSON
- Postman → Body → raw → JSON
- 파라미터가 없거나 다르다면?
- HTTP 상태코드 405 Unsupported Media Type Exception 발생
- 속성 작성 방법
- consumes=”application/json”
- application/json 미디어 타입 허용
- consumes=”!application/json”
- application/json 제외 미디어 타입 허용
- consumes=”application/*”
- application/ 으로 시작하는 모든 미디어 타입 허용
- consumes=”*\\/*”
- 모두 허용
- consumes=”application/json”
MediaType 매핑 produces(제공)
- 요청 헤더의 Accept 값에 따라서 produces 하는 값이 변한다.
@RestController
public class ParameterController {
// produces 속성값 추가
@GetMapping(value = "/users", produces = "text/plain")
public String produces() {
// logic
String result = "text/plain 데이터 응답";
return result;
}
}
- HTTP 요청 Accept Header에 Media Type이 있어야한다.
- **/** : 전체 Media Type 허용
- 실행결과
- consumes 속성 사용법과 같다.
- 위에 나온 모든 MediaType은 Spring이 제공하는 Enum을 사용하면 된다.
Spring이 지원하는 Parameter
📌 어노테이션 기반 Spring의 Controller는 다양한 파라미터를 쉽게 사용할 수 있도록 지원한다.
- HTTP 헤더 조회
- Spring에서 요청 Header에 쉽게 접근할 수 있다.
- HttpServletRequest와 같이 파라미터로 다룰 수 있다.
- Controller 예시
- Spring에서 요청 Header에 쉽게 접근할 수 있다.
// 로깅
@Slf4j
@RestController
public class RequestHeaderController {
@GetMapping("/request/headers")
public String headers(
HttpServletRequest request, // Servlet에서 사용한것과 같음
HttpServletResponse response, // Servlet에서 사용한것과 같음
@RequestHeader MultiValueMap<String, String> headerMap,
@RequestHeader("host") String host,
@CookieValue(value = "cookie", required = false) String cookie,
HttpMethod httpMethod,
Locale locale
) {
// Servlet
log.info("request={}", request);
log.info("response={}", response);
// @RequestHeader
log.info("headerMap={}", headerMap);
log.info("host={}", host);
// @CookieValue
log.info("cookie={}", cookie);
// HttpMethod
log.info("httpMethod={}", httpMethod);
// Locale
log.info("Locale={}", locale);
return "success";
}
}
- Postman API 호출
Log 출력 결과
- request
- HttpServletRequest 객체 주소 값
- response
- HttpServletRequest 객체 주소 값
- headerMap :
hashMap={
user-agent=[PostmanRuntime/7.35.0],
accept=[*/*],
postman-token=[5f324c1c-7902-4750-9e01-2c4d093e8ad6],
host=[localhost:8080],
accept-encoding=[gzip, deflate, br],
connection=[keep-alive]
}
- host
- host 정보
- cookie
- Header의 Cookie 값
- httpMethod
- 호출에 사용한 HttpMethod
- Locale
- 위치 정보를 나타내는 헤더
- 우선순위가 존재한다.
MultiValueMap
Map과 유사하게 Key, Value 형식으로 구현되어 있지만 하나의 Key가 여러 Value를 가질 수 있다 HTTP Header, Reqeust Parameter와 같이 하나의 Key에 여러 값을 받을 때 사용한다.
ex ) key1=value1&key1=value2
MultiValueMap<String, String> linkedMultiValuemap = new LinkedMultiValueMap();
// key1에 value1 저장
linkedMultiValuemap.add("key1", "value1");
// key1에 value2 저장
linkedMultiValuemap.add("key1", "value2");
// key1에 저장된 모든 value get
List<String> values = linkedMultiValuemap.get("key1");
'Back-End (Web) > Spring' 카테고리의 다른 글
[Spring] HTTP Message Body & TEXT (0) | 2024.12.18 |
---|---|
[Spring] @RequestParam & @ModelAttribute (0) | 2024.12.17 |
[Spring] Spring Annotation (1) | 2024.12.15 |
[Spring] Spring MVC 패턴 (1) | 2024.12.14 |
[Spring] Spring Boot (0) | 2024.12.10 |