RequestMappingHandlerAdapter에 의해 동작되는 애노테이션 기반 스프링 컨트롤러는 다양한 파라미터를 지원한다.
먼저 헤더 정보를 조회해보자
package hello.springmvc.basic.request;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class RequestHeaderController {
@RequestMapping("/headers")
public String headers(HttpServletRequest request,
HttpServletResponse response,
HttpMethod httpMethod,
Locale locale, @RequestHeader MultiValueMap<String, String> headerMap,
@RequestHeader("host") String host,
@CookieValue(value = "myCookie", required = false) String cookie){
log.info("request={}", request);
log.info("response={}", response);
log.info("httpMethod={}", httpMethod);
log.info("locale={}", locale);
log.info("headerMap={}", headerMap);
log.info("header host={}", host);
log.info("myCookie={}", cookie);
return "ok";
}
}
1. HttpServletRequest, HttpServletResponse - 원래 사용하던 서블릿 기반 request, response 객체이다.
2. HttpMethod -> GET, POST, PATCH, PUT, DELETE와 같은 HTTP 메서드를 가져올 수 있다.
3. LOCALE -> 스프링에서는 로케일이 여러개 올 경우 로케일 리졸버가 동작한다 (이건 MVC 2편에서 설명함)
-> 여기에는 쿠키 세션을 어디에 저장할지 설정할 수 있는데 기본은 HTTP가 보내는 것에 의해 결정된다.
4. @RequestHeader MultiValueMap<String, String>
헤더에 입력된 정보를 Key, Value 형태로 전부 긁어온다 이 때, 1개의 Key에 여러 Value를 저장할 수 있도록 허용하는게 MultiValueMap
HTTP Header나 HTTP Parameter와 같이 하나의 키에 여러 값을 받을 때 사용한다.
5. @CookieValue(value = "myCookie", required = false) -> 이 경우 쿠키를 긁어온다(조회)(. / 필수는 아님(required = false)
HTTP 요청 파라미터 - 쿼리 파라미터 , HTML Form
클라이언트 -> 서버로 요청 데이터를 전달하는 방식은 다음 3가지를 가진다.
GET - 쿼리 파라미터 (/url?username=홍길동&age=20)
-> 메세지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달하는 방식
POST - HTML FORM
content-type : application/x-www-form-urlencoded
메세지 바디에 쿼리 파라미터 형식으로 전달
HTTP 메세지 바디에 데이터를 직접 받아서 요청
주로 JSON, XML, TEXT로 보내는데 HTTP API에서 주로 사용
데이터 형식은 주로 JSON 사용
POST,PUT,PATCH 모두 사용 가능
GET 쿼리 파라미터 전송방식 / POST HTML FORM 전송방식 둘 다 형식이 같아서 구분 없이 조회 가능 - 요청 파라미터 조회!
package hello.springmvc.basic.request;
import hello.springmvc.basic.HelloData;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j
@Controller
public class RequestParamController {
// 요청 파라미터 조회 1.
@RequestMapping("/request-param-v1")
public void requestParamV1(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
log.info("username={}, age={}", username, age);
response.getWriter().write("ok");
}
// 요청 파라미터 조회 2.
@ResponseBody // 아니면 @RestController -> 뷰 조회 X
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam("username") String memberName,
@RequestParam("age") int memberAge
){
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
// 요청 파라미터 조회 3.
@ResponseBody // 아니면 @RestController -> 뷰 조회 X
@RequestMapping("/request-param-v3")
public String requestParamV3(
@RequestParam String memberName,
@RequestParam int memberAge
){
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
// 요청 파라미터 조회 4. ambiguity로 인해 권장하지 않음
@ResponseBody // 아니면 @RestController -> 뷰 조회 X
@RequestMapping("/request-param-v4")
public String requestParamV4(
String memberName, // 단 요청 파라미터 이름과 동일해야 함.
int memberAge
){
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
}
1. requestParamV1 - 이전 방식으로 서블릿을 통해 받아올 request parameter를 조회했다.
2. requestParamV2 - @RequestParam의 등장
@RequestParam(name,required) - 파라미터 이름으로 바인딩 name에 파라미터 이름, required는 필수 여부
필수인데 값이 오지 않을 경우 400 발생
@ResponseBody - 뷰 조회를 무시하고 HTTP 메세지 바디에 그대로 return된 값 입력.
파라미터 이름과 변수 이름이 같은 경우 name은 생략 가능, 아예 애노테이션 생략해버리는 V4는 ambiguous하기 때문에 권장 X
애노테이션이 아예 없는 경우 required는 기본값으로 false를 갖는다. / 원래는 기본값 true임.
required가 false인 경우, primitive 타입 대신 Wrapper 클래스를 이용해야 함
primitive형에는 NULL이 입력될 수 없음(참조형 객체가 아님), null을 받을 수 있는 Integer로 변경하거나, default value를 사용하자.
https://stackoverflow.com/questions/1894149/is-null-an-object
Is null an Object?
Is null an Object in Java?
stackoverflow.com
NULL에 관한 정보를 같이 첨부한다.
/**
* @RequestParam
* - defaultValue 사용 *
* 참고: defaultValue는 빈 문자의 경우에도 적용 * /request-param-default?username=
*/
@ResponseBody
@RequestMapping("/request-param-default")
public String requestParamDefault(
@RequestParam(required = true, defaultValue = "guest") String username,
@RequestParam(required = false, defaultValue = "-1") int age) {
log.info("username={}, age={}", username, age);
return "ok";
}
파라미터에 값이 없는 경우 defaultValue의 사용을 통해 기본값 적용 가능, required 의미 없어짐
-> 참고로 이 속성 사용시 빈 문자의 경우에도 설정한 기본값이 적용된다.
반면 required의 경우 null과 빈 문자("")를 다르게 처리한다.
/**
* @RequestParam Map, MultiValueMap
* Map(key=value)
* MultiValueMap(key=[value1, value2, ...]) ex) (key=userIds, value=[id1, id2])
*/
@ResponseBody
@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String, Object> paramMap) {
log.info("username={}, age={}", paramMap.get("username"),
paramMap.get("age"));
return "ok";
}
파라미터를 Map, MultiValueMap으로 조회할 수 있다.
파라미터 값이 1개가 확실하다면 Map쓰되, 아니면 MultiValueMap써라 (-> 근데 대부분 1개다)
'스프링 공부 (인프런 김영한 선생님) > 스프링 MVC 1편' 카테고리의 다른 글
[스프링 웹 MVC 1편] 23. HTTP 요청 파라미터 (JSON) (0) | 2023.06.03 |
---|---|
[스프링 웹 MVC 1편] 22. HTTP 요청 파라미터 (@ModelAttribute, 단순 텍스트) (0) | 2023.06.03 |
[스프링 웹 MVC 1편] 20. 스프링 MVC - 기본기능 (요청매핑) (0) | 2023.06.03 |
[스프링 웹 MVC 1편] 19. 스프링 MVC - 기본 기능 (로깅) (0) | 2023.06.01 |
[스프링 웹 MVC 1편] 18. 스프링 MVC - 시작 (0) | 2023.05.30 |