@Controller 애노테이션을 이용해서 RequestMappingHandler를 만들게 되면 자동으로 컴포넌트스캔에 의해서 자동으로 스프링빈에 등록되어서 RequestMappingHandler와 RequestMappingHandlerAdapter에 의해서 컨트롤러가 호출될 수 있다고 했다.
그밖에도 @Controller 애노테이션을 활용한 컨트롤러는 다양한 인자를 제공할 수 있으며, 자세한 내용은 아래의 가이드 페이지에서 확인할 수 있다.
이전 공부했었던 내용으로 몇가지 예시를 들면 아래와 같다.
@RequestMapping("/headers")
public String headers(HttpServletRequest request,
HttpServletRequest 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";
}
위 코드를 postman으로 아래와같이 요청했을때의 수행결과는 다음과 같다.
2023-07-18 21:52:13.802 INFO 23492 --- [nio-8080-exec-9] h.s.b.request.RequestHeaderController : request=org.apache.catalina.connector.RequestFacade@7ea44152
2023-07-18 21:52:13.803 INFO 23492 --- [nio-8080-exec-9] h.s.b.request.RequestHeaderController : response=org.apache.catalina.connector.RequestFacade@7ea44152
2023-07-18 21:52:13.803 INFO 23492 --- [nio-8080-exec-9] h.s.b.request.RequestHeaderController : httpMethod=POST
2023-07-18 21:52:13.803 INFO 23492 --- [nio-8080-exec-9] h.s.b.request.RequestHeaderController : locale=ko_KR
2023-07-18 21:52:13.803 INFO 23492 --- [nio-8080-exec-9] h.s.b.request.RequestHeaderController : headerMap={content-type=[application/json], cookie=[myCookie=1], user-agent=[PostmanRuntime/7.32.3], accept=[*/*], postman-token=[be571024-3fe3-48e8-8966-742b920f1d5e], host=[localhost:8080], accept-encoding=[gzip, deflate, br], connection=[keep-alive], content-length=[37]}
2023-07-18 21:52:13.803 INFO 23492 --- [nio-8080-exec-9] h.s.b.request.RequestHeaderController : header host=localhost:8080
2023-07-18 21:52:13.803 INFO 23492 --- [nio-8080-exec-9] h.s.b.request.RequestHeaderController : myCookie=1
HttpServletRequest : @Controoler에서도 Servlet에서 사용하던 HttpServletRequest값을 사용할 수 있다.
HttpServletResponse : @Controoler에서도 Servlet에서 사용하던 HttpServletResponse 값을 사용할 수 있다.
Local : locale 값 확인 가능
@RequestHeader("host)" : HttpRequestHeader중에서 host 정보를 가져온다.
@CookieValue(value = "myCookie", required=false) : 저장된 쿠키값을 조회한다.
클라이언트에서 서버로 요청 데이터를 전달할때는 주로 3가지 방법을 사용한다고 한다.
GET - 쿼리파라미터 방식
POST - Html Form 방식
Http Message Body에 데이터를 직점 담는 방식
Get방식과 HtmlForm 방식은 Spring에서 @RequestParam 애노테이션으로 모두 조회가 가능하다.
@RequestParam은 HttpServletRequest에서의 getParameter를 이용한 조회방식과 동일하다.
Get방식과 Html Form 방식은 SpringMVC에서 @RequestParam 애노테이션을 이용해서 손쉽게 조회가 가능하다. 그러나, 좀 더 편리하게 사용하기 위해서 몇가지 알아야할 점이 있다.
@ResponseBody
@RequestMapping("/request-param-v1")
public String requestParamV1(
@RequestParam("username") String username, @RequestParam("age") int age) {
log.info("username : {}", username);
log.info("age : {}", age);
return "success";
}
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam String username, @RequestParam int age) {
log.info("username : {}", username);
log.info("age : {}", age);
return "success";
}
@ResponseBody
@RequestMapping("/request-param-v3")
public String requestParamV3(
String username, int age) {
log.info("username : {}", username);
log.info("age : {}", age);
return "success";
}
@ResponseBody
@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String, Object> paramMap) {
log.info("username={}, age={}", paramMap.get("username"), paramMap.get("age"));
return "success";
}
따라서, 위 3가지 코드는 모두 같은 기능을 수행한다.
참고) RequestBody는 return값을 그대로 Http 메시지 Body에 되돌려주도록 명시합니다.
그뿐만 아니라 RequestParam은 Map 컬렉션으로 조회도 가능합니다.
@RequestParam이 단순한 데이터의 쿼리 파라미터를 조회하는 애노테이션이었다면 일반적인 객체들을 조회할 수 있도록 지원하는 애노테이션도 존재합니다.
일반적으로는 @RequestParam으로 쿼리 파라미터를 조회하고 나서 객체를 만들어주지만, Spring에서는 이 과정을 자동화해주는 @ModelAttribute라는 애노테이션이 존재합니다.
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute Member member) {
log.info("username={}, age={}", member.getUsername(), member.getAge());
return "success";
}
@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV2(Member member) {
log.info("username={}, age={}", member.getUsername(), member.getAge());
return "success";
}
위 코드는 아래와 같이 실행됩니다.
요청 파라미터가 아닌 Http Body에 Message가 담겨 전달되는 경우는 RequestParam과 ModelAttribute로 조회가 불가능하다.
따라서 SpringMVC에서는 아래와 같은 파라미터를 지원합니다.
HttpEntity를 사용하면 메시지 바디에 직접 정보를 추가해서 반환도 가능합니다.
(ResponseEntity도 물론 가능)
HttpEntity
RequestEntity
ResponseEntity
@RequestBody
@ResponseBody
정리하자면
요청 파라미터 : @ReuqestParam, @ModelAttribute
Http 메시지 바디 : @RequestBody @ResponseParam
@PostMapping("/request-body-string-v1")
public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
response.getWriter().write("success");
}
@PostMapping("/request-body-string-v2")
public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException {
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
responseWriter.write("success");
}
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) throws IOException {
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("success");
}
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
log.info("messageBody={}", messageBody);
return "success";
}
그리고 @RequestBody는 ModelAttribute처럼 일반 객체로 한번에 변환도 가능하다.
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody Member member) {
log.info("username={}, age={}", member.getUsername(), member.getAge());
return "success";
}
해당 포스팅은 아래의 강의를 공부 후 개인적으로 정리한 내용입니다.
김영한님의 SpringMVC1편-요청매핑 API
김영한님의 SpringMVC1편-쿼리파라미터,HtmlForm
김영한님의 SpringMVC1편-@RequestParam
정보가 많아서 도움이 많이 됐습니다.