어노테이션 기반 Spring의 Controller는 다양한 파라미터를 지원한다
@Controller 메서드 인수
- @PathVariable : URL 템플릿 변수에 액세스합니다
- RequestParam : 멀티파트 파일을 포함한 서블릿 요청 매개변수에 대한 액세스용. 매개 변수 값 선언된 메서드 인수 형식으로 변환됩니다
@RequestBody : HTTP 요청 본문에 액세스 본문 내용은 선언된 메서드로 변환
HTTP 헤더 조회
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
) {
log.info("request={}", request);
log.info("response={}", response);
log.info("headerMap={}", headerMap);
log.info("host={}", host);
log.info("cookie={}", cookie);
log.info("httpMethod={}", httpMethod);
log.info("Locale={}", locale);
return "success";
}
}
PostAPI 호출
log 출력 결과
- request : Servlet에서 사용한것과 같음
- response : Servlet에서 사용한것과 같음
- 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]
}
4. host : host정보
5. cookie : Head의 Cookie
6. httpMethod : 호출에 사용한 HttpMethod
7. locale : 위치정보를 나타내는 헤더 우선순위가 존재한다. ( 한국기준 1순위 : ko, 2순위 : eng)
MultiValueMap
- Map과 유사하게 Key, Value 형식으로 구현되어 있지만, 하나의 Key가 여러 Value를 가질 수 있다
HTTP Header, Reqeust Parameter와 같이 하나의 Key에 여러 값을 받을 때 사용한다 ex) key1=value1&key1=value2
ex)
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");
Query Parameter, HTML Form Data
위 두가지 경우의 요청 파라미터 Spring에서 Mapping
HttpServletRequest.getParameter(”key”)
@RequestParam 어노테이션
Client에서 Server로 Data를 전달하는 3가지 방법
1. GET - Query Param
- URL의 쿼리 파라미터를 사용하여 데이터 전달
<http://localhost:8080/param?**key1=value1&key2=value2**>
ex) Controller
@Slf4j
@Controller
public class RequestParamController {
@GetMapping("/request/params")
public void params(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String key1Value = request.getParameter("key1");
String key2Value = request.getParameter("key2");
log.info("key1Value={}, key2Value={}", key1Value, key2Value);
response.getWriter().write("success");
}
}
2. POST - HTML Form(x-www-form-urlencoded)
- Request Body에 쿼리 파라미터 형태로 전달
POST /param
content-type: application/x-www-form-urlencoded
key1=value1&key2=value2
ex) Controller
@Slf4j
@Controller
public class RequestBodyController {
@PostMapping("/request/body")
public void requestBody(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String key1Value = request.getParameter("key1");
String key2Value = request.getParameter("key2");
log.info("key1Value={}, key2Value={}", key1Value, key2Value);
response.getWriter().write("success");
}
}
3. HTTP RequestBody - 데이터(JSON, TEXT, XML 등)를 직접 담아서 사용
- 주로 @RestController에서 사용한다, 대부분 JSON으로 데이터 전달 ex) POST, PUT, PATCH Method에서 사용 GET, DELETE는 거의 Body가 없음 → 권장X
@RequestParam
URL에서 파라미터 값과 이름을 함께 전달하는 방식으로 주로 HTTP 통신 Method 중 GET 방식의 통신을 할 때 많이 사용한다.
Spring이 제공하는 해당 어노테이션을 사용하면 요청 파라미터값에 아주 쉽고 간편하게 접근(바인딩)할 수 있다
ex)
@Controller
public class RequestParamController {
@ResponseBody
@GetMapping("/request/param")
public String requestParam (
@RequestParam("name") String userName,
@RequestParam("age") int userAge
) {
// logic
return "success";
}
}
- @Controller 이지만 Method에 @ResponseBody를 붙이게되면 View를 찾는것이 아니라 ResponseBody 데이터에 “success”가 들어간다. → 위 코드가 @RestController의 원본코드라 생각하시면 됩니다.
- @RequestParam : 파라미터 이름으로 바인딩
- @RequestParam(”속성값”) : 속성값이 파라미터 이름으로 매핑된다
- “속성값”과 변수명이 같으면 생략이 가능하다. ex) @RequestParam(name) String name
// GET http://localhost:8080/request/param?name=wonuk&age=100
@Controller
public class RequestParamController {
@ResponseBody
@GetMapping("/request/param")
public String requestParam (
@RequestParam String name,
@RequestParam int age
) {
// logic
return "success";
}
}
5. 충격적이게도 사실 모두 생략해도된다. 참고 : 생략하면 (required=false) 속성이 default로 설정된다
// GET http://localhost:8080/request/param?name=wonuk&age=100
@Controller
public class RequestParamController {
@ResponseBody
@GetMapping("/request/param")
public String requestParam (
String name,
int age
) {
// logic
return "success";
}
}
- 단, 요청 파라미터와 이름이 완전히 같아야함
- 단순 타입(int, String, Integer 등)이어야 한다
하지만 위의 방식은 권장하지 않는다, 명시적으로 표시되어있지 않으면 팀의 협의가 있지 않다면, 다른 개발자들에게 혼동을주기 충분하다.
@RequestParam이 있어야 요청 파라미터에서 데이터를 읽는구나 하게된다
파라미터 필수 여부 설정 required 속성
API 스펙을 규정할 때 사용, 필수값 설정
@Controller
public class RequestParamController {
@ResponseBody
@GetMapping("/request/param")
public String requestParam (
@RequestParam(required = true) String name, // 필수
@RequestParam(required = false) int age // 필수가 아님
// @RequestParam(required = false) Integer age
) {
// logic
return "success";
}
}
- @RequestParam을 사용하면 기본 Default값은 True이다.
- True 설정된 파라미터에 값이 존재하지 않으면 400 BadRequest Error
- Exception이 발생하지 않는 경우
- ex) http://localhost:8080/request/param?name=wonuk → Exception 이 발생하지 않으려면, age=0혹은, Integer 형태로 바꿔 주어야한다.
- ex) http://localhost:8080/request/param?name=wonuk&age=100
- Exception이 발생하는 경우
- ex) http://localhost:8080/request/param?age=100
- ex) http://localhost:8080/request/param
- required = false 설정이 되어있으면 해당 파라미터는 없어도 된다.
- 하지만! 여기서 만약 http://localhost:8080/request/param?name=wonuk 로 요청한다면?
- 500 Error가 발생한다
- int Type에는 null을 넣을 수 없기 때문에! 0이라도 들어가야한다 Integer = null
- 따라서 보통 null을 허용하는 Integer로 사용하거나 default 옵션을 사용한다.
- 파라미터 Key값만 있고 Value가 없는 경우 http://localhost:8080/request/param?name=
- null과 빈 문자열 “”은 다르다!
- 위 형태는 빈 문자열 “” 로 인식한다, True지만 통과가 되어버린다. 주의해야함
- default 속성 적용 (기본값)
@Controller
public class RequestParamController {
@ResponseBody
@GetMapping("/request/param")
public String requestParam (
@RequestParam(required = true, defaultValue = "wonuk") String name,
@RequestParam(required = false, defaultValue = "1") int age
) {
// logic
return "success";
}
}
- name Parameter 의 값이 없으면 기본적으로 “wonuk”으로 설정한다
- ex) http://localhost:8080/request/param?age=100
- ex) http://localhost:8080/request/param
- age Parameter의 값이 없으면 기본적으로 0 으로 설정한다
- ex) http://localhost:8080/request/param?name=wonuk
- ex) http://localhost:8080/request/param
- defaultValue 속성을 설정하게 되면 “” 빈문자열의 경우에도 기본값이 설정된다. 주의
8. Map 으로 조회
@Controller
public class RequestParamController {
@ResponseBody
@GetMapping("/request/param")
public String requestParam (
@RequestParam Map<String, Object> paramMap
) {
// logic
String name = paramMap.get("name");
Integer age = paramMap.get("age");
return "success";
}
}
- Map 형태로 조회가 가능하다
- ex) key=value
- ex) http://localhost:8080/request/param?name=wonuk&age=100
- MultiValueMap 형태로 조회가 가능하다
- ex) key=[value1, value2]
- ex) http://localhost:8080/request/param?name=wonuk1&name=wonuk2&name=wonuk3
파라미터 Map의 Value가 1개인 경우에는 Map, 여러개인 경우 MultiValueMap을 사용한다 하지만 대부분 한개인 경우로 구성되어 있다.
'TIL' 카테고리의 다른 글
TIL 240610 예외 처리 변경 (0) | 2024.06.11 |
---|---|
TIL 240607 Spring Request Mapping (0) | 2024.06.10 |
TIL 240604 Annotation (0) | 2024.06.05 |
TIL 240603 인증, 인가 (0) | 2024.06.04 |
TIL 240531 Validation (0) | 2024.05.31 |