Search
Duplicate
📒

[Spring Study] 05-1. HTTP 요청 어노테이션

상태
완료
수업
Spring Study
주제
Converter
4 more properties
참고

HTTP 요청 메소드 어노테이션

@Controller, @RestController

NOTE
스프링이 자동으로 스프링 Bean으로 등록해주며, Controllr의 기능을한다!
@Controller // Controller 동작 public class MemberController {} @RestController // 반환값으로 View가 아닌, HTTP 메시지바디에 입력 // @ResponseBody + @Controller public class MemberController {}
Java
복사

@RequestMapping

NOTE
클라이언트 요청에 정보를 어떤 Controller가 처리할지를 맵핑하기 위한 어노테이션이다!
@RequestMapping("/members") public class MemberController {}
Java
복사
대부분의 속성들은 배열[] 형태로 제공되며, 이를 통해 다중 설정이 가능합니다 {"/hello-basic", "/hello-go"}
URL의 끝에 /가 붙어도, /를 생략한 URL로 매핑해줍니다. /hello-basic == /hello-basic/

PathVariable(경로 변수) 사용

NOTE
PathVariable은 경로의 일부를 변수로 사용할 수 있습니다.
@GetMapping("/mapping/{userId}") public String mappingPath(@PathVariable("userId") String data) { log.info("mappingPath userId={}", data); return "ok"; } // 경로 변수와 변수가 이름이 동일하면 생략가능 @GetMapping("/mapping/{userId}") public String mappingPath(@PathVariable String userId) { log.info("mappingPath userId={}", data); return "ok"; } // 다중으로 사용 가능 @GetMapping("/mapping/users/{userId}/orders/{orderId}") public String mappingPath(@PathVariable String userId, @PathVariable Long orderId) { log.info("mappingPath userId={}, orderId={}", userId, orderId); return "ok"; }
Java
복사

HTTP 메서드(Get, Post, Put, Delete, Patch)

NOTE
@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 userId=" + userId; } /** * DELETE /mapping/users/{userId} - 유저 삭제 */ @DeleteMapping("/{userId}") public String deleteUser(@PathVariable String userId) { return "delete userId=" + userId; } }
Java
복사
Http 메서드를 축약한 어노테이션을 사용하는 것이 더 직관적이다.

특정 조건 매핑(params, headers, consumes, produces)

NOTE
// params에 mode=debug가 있어야 호출된다. @GetMapping(value = "/mapping-header", params = "mode=debug") public String mappingHeader() { log.info("mappingHeader"); return "ok"; } // header에 mode=debug가 있어야 호출된다. @GetMapping(value = "/mapping-header", headers = "mode=debug") public String mappingHeader() { log.info("mappingHeader"); return "ok"; }
Java
복사
param = 을 추가하여, 특정 조건에 대한 매핑을 수행할 수 있다.
// consumes = Content-Type 헤더을 제한합니다. // 충족되지 않으면 415 코드를 반환한다. @PostMapping(value = "/mapping-consume", consumes = "application/json") public String mappingConsumes() { log.info("mappingConsumes"); return "ok"; } // produce = Accept을 제한합니다. // Accept헤더가 이를 수용하지 않으면 406 에러를 반환합니다. @GetMapping(value = "/mapping-produce", produces = "text/html") public String mappingHeader() { log.info("mappingHeader"); return "ok"; }
Java
복사
Content-Type 헤더 기반 추가 매핑 Media Type (요청 헤더의 Content - type)

HTTP 요청 파라미터 어노테이션

@RequestParam

Note
@RequestParam은 요청 파라미터를 전달할 때 사용됩니다.
// http://localhost:8080/request-param-v2?username=hello&age=20 @ResponseBody @RequestMapping("/request-param-v2") public String requestParamV2( @RequestParam("username") String username, @RequestParam("age") int age) { log.info("username={}, age={}", username, age); return "ok"; } // 변수명이 돌일하면 (name="xxx") 이름 생략이 가능하다. @ResponseBody @RequestMapping("/request-param-v3") public String requestParamV3( @RequestParam String username, @RequestParam int age) { log.info("username={}, age={}", username, age); return "ok"; } // 변수명이 동일하고 기본타입이면 @RequestParam도 생략이 가능하다. (기본 컨버터 지원) @ResponseBody @RequestMapping("/request-param-v4") public String requestParamV4(String username, int age) { log.info("username={}, age={}", username, age); return "ok"; }
Java
복사
// required: 필수값을 설정할 수 있다. (없을시 400에러) @ResponseBody @RequestMapping("/request-param-required") public String requestParamRequired( @RequestParam(required = true) String username, @RequestParam(required = false) int age) { log.info("username={}, age={}", username, age); return "ok"; } // defaultValue: 파라미터에 값이 없는 경우 기본 값을 적용한다. @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"; } // Map 조회: 파라미터의 값이 여러개인 경우 map으로 받을 수 있다. @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"; }
Java
복사

@ModelAttribute

NOTE
@ModelAttribute는 HTTP 요청 파라미터를 객체에 바인딩 하는데 사용할 수 있습니다.
// @ModelAttribute: 스프링MVC가 자동으로 요청 파라미터에 알맞게 객체생성 // 단 주입을 기반으로 하기에 생성자와 setter가 필수이다. @ResponseBody @RequestMapping("/model-attribute-v1") public String modelAttributeV1(@ModelAttribute HelloData helloData) { log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); return "ok"; }
Java
복사
작동 과정
요청 파라미터의 이름으로 HelloData 객체의 프로퍼티를 찾습니다.
해당 프로퍼티의 생성자 또는 setter를 호출하여 파라미터의 값을 입력(바인딩)합니다.
바인딩 오류
age=abc와 같이 숫자가 들어가야 하는 곳에 문자를 입력하면 BindException이 발생합니다.
이런 바인딩 오류를 처리하는 방법은 검증 부분에서 다룹니다.
요청 파라미터와 다르게 HTTP 메시지 바디를 통해 데이터가 직접 넘어오는 경우 @RequestParam, @ModelAttribute를 사용할 수 없다.

HTTP 요청 파라미터 지원타입

HttpServletRequest

NOTE
HttpServletRequest의 입력 스트림으로부터 JSON 데이터를 직접 읽어 사용할 수 있습니다.
@PostMapping("/request-body-json-v1") public void requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException { // 객체 변환 ServletInputStream inputStream = request.getInputStream(); String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); log.info("messageBody={}", messageBody); // Jackson의 ObjetMapper를 사용해 역직렬화 HelloData helloData = objectMapper.readValue(messageBody, HelloData.class); log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); response.getWriter().write("ok"); }
Java
복사
HttpServletRequest를 사용해서 직접 HTTP 메시지 바디에서 데이터를 읽어와서 문자로 변환한다

HttpEntity

NOTE
HttpEntity를 사용하면 HTTP 요청의 헤더와 본문을 래핑해서 받을 수 있습니다.
@ResponseBody @PostMapping("/request-body-json-v4") public String requestBodyJsonV4(HttpEntity<HelloData> data) throws IOException { HelloData helloData = data.getBody(); log.info("messageBody={}", helloData); log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); return "ok"; }
Java
복사
HttpEntity를 이용해서 요청 파라미터를 처리할 수 있다.

@RequestBody 객체 변환

NOTE
@RequestBody을 사용하면 HTTP 요청 본문을 객체로 변환할 수 있습니다. 이 때 스프링은 httpMessageConverterMappingJackson2HttpMessageConvertes를 사용하여 자동으로 JSON데이터를 자바 객체로 변환합니다.
@ResponseBody @PostMapping("/request-body-json-v3") public String requestBodyJsonV3(@RequestBody HelloData helloData) throws IOException { log.info("messageBody={}", helloData); log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); return "ok"; }
Java
복사
여기서 HelloData객체에는 일반적으로 생성자 or setter함수로 객체가 생성되어야 하지만, 2개의 요소가 모두 없더라도 Jackson라이브러리가 리플렉션을 통해 값을 초기화해줍니다.