HTTP 메서드 매핑
PathVariable(경로 변수)
- URL 경로에 동일한 패턴의 가변 값을 받아서 처리하기 위할 때 사용
/**
* PathVariable 사용
* 변수명이 같으면 생략 가능
* @PathVariable("userId") String userId -> @PathVariable String userId
*/
@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String data) {
log.info("mappingPath userId={}", data);
return "ok";
}
특정 조건 매핑
- 파라미터
- 헤더
- 미디어 타입 조건 매핑 - HTTP 요청 Content-Type, consume
- 미디어 타입 조건 매핑 - HTTP 요청 Accept, produce
/**
* 파라미터로 추가 매핑
* params="mode",
* params="!mode"
* params="mode=debug"
* params="mode!=debug" (! = )
* params = {"mode=debug","data=good"}
*/
@GetMapping(value = "/mapping-param", params = "mode=debug")
/**
* 특정 헤더로 추가 매핑
* headers="mode",
* headers="!mode"
* headers="mode=debug"
* headers="mode!=debug" (! = )
*/
@GetMapping(value = "/mapping-header", headers = "mode=debug")
/**
* Content-Type 헤더 기반 추가 매핑 Media Type
* 오류시 415 상태코드 반환
* consumes="application/json"
* consumes="!application/json"
* consumes="application/*"
* consumes="*\/*"
* MediaType.APPLICATION_JSON_VALUE
*/
@PostMapping(value = "/mapping-consume", consumes = "application/json")
/**
* Accept 헤더 기반 Media Type
* 오류시 406 상태코드 반환
* produces = "text/html"
* produces = "!text/html"
* produces = "text/*"
* produces = "*\/*"
*/
@PostMapping(value = "/mapping-produce", produces = "text/html")
HTTP 요청 파라미터
쿼리 파라미터, HTML Form
(url들어가고)?username="test"
request.getParameter("username");
@RequestParam
- 파라미터 이름으로 바로 바인딩 가능
- 속성명과 파라미터명이 같으면 내부 이름 생략 가능
- 파라미터 필수 설정 가능
- default는 true
- defaultValue 설정 가능
public String requestParamV2(
@RequestParam("username") String memberName,
@RequestParam(required = false, defaultValue = "-1") int memberAge) {
}
@ModelAttribute
- 뒤에 나오는 객체에 알맞게 찾아 값을 넣어준다
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
}
public String modelAttributeV1(HelloData helloData) {
}
- 생략 가능
- String, int, Integer 같은 단순 타입 = @RequestParam
- 나머지 = @ModelAttribute (argument resolver로 지정해둔 타입 외)
HTTP 요청 메시지
단순 텍스트
- HTTP message body에 데이터를 직접 담아서 요청
- HTTP API에서 주로 사용, JSON, XML, TEXT
- 데이터 형식은 주로 JSON
- POST, PUT, PATCH
@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);
}
/**
* InputStream(Reader): HTTP 요청 메시지 바디의 내용을 직접 조회
* OutputStream(Writer): HTTP 응답 메시지의 바디에 직접 결과 출력
*/
@PostMapping("/request-body-string-v2")
public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException {
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
}
/**
* HttpEntity: HTTP header, body 정보를 편리하게 조회
* - 메시지 바디 정보를 직접 조회(@RequestParam X, @ModelAttribute X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*
* 응답에서도 HttpEntity 사용 가능
* - 메시지 바디 정보 직접 반환(view 조회X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*/
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
String messageBody = httpEntity.getBody();
}
/**
* @RequestBody
* - 메시지 바디 정보를 직접 조회(@RequestParam X, @ModelAttribute X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*
* @ResponseBody
* - 메시지 바디 정보 직접 반환(view 조회X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*/
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
}
JSON
public class RequestBodyJsonController {
private ObjectMapper objectMapper = new ObjectMapper();
@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);
HelloData data = objectMapper.readValue(messageBody, HelloData.class);
}
/**
* @RequestBody
* HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*
* @ResponseBody
* - 모든 메서드에 @ResponseBody 적용
* - 메시지 바디 정보 직접 반환(view 조회X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*/
@ResponseBody
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
HelloData data = objectMapper.readValue(messageBody, HelloData.class);
}
/**
* @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림)
* HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter (content-type: application/json)
*
*/
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData data) {
}
}
HTTP 응답
정적 리소스, 뷰 템플릿
- String을 반환하는 경우 - View or HTTP 메시지
- @ResponseBody 가 없으면 뷰 리졸버가 실행되어서 뷰를 찾고 렌더링 한다
- @ResponseBody 가 있으면 뷰 리졸버를 실행하지 않고 HTTP 메시지 바디에 직접 문자를 입력한다
- void를 반환하는 경우
- @Controller를 사용하고 HttpServletResponse, OutputStream(Writer) 같은 HTTP 메시지 바디를 처리하는 파라미터가 없으면 요청 URL을 참고해서 논리 뷰 이름으로 사용
- 그냥 사용 권장 안함
- HTTP 메시지
- @ResponseBody, HttpEntity를 사용하면 뷰 템플릿을 사용하는 것이 아니라 HTTP 메시지 바디에 직접 응답 데이터를 출력할 수 있다.
HTTP API, 메시지 바디에 직접 입력
@Slf4j
@Controller
//@RestController
public class ResponseBodyController {
@GetMapping("/response-body-string-v1")
public void responseBodyV1(HttpServletResponse response) throws IOException {
response.getWriter().write("ok");
}
/**
* HttpEntity, ResponseEntity(Http Status 추가)
* @return
*/
@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("ok", HttpStatus.OK);
}
@ResponseBody
@GetMapping("/response-body-string-v3")
public String responseBodyV3() {
return "ok";
}
@GetMapping("/response-body-json-v1")
public ResponseEntity<HelloData> responseBodyJsonV1() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return new ResponseEntity<>(helloData, HttpStatus.OK);
}
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return helloData;
}
}
HTTP 메시지 컨버터
- HTTP 요청 : @RequestBody, HttpEntity(RequestEntity)
- HTTP 응답 : @ResponseBody, HttpEntity(ResponseEntity)
메시지 컨버터
- ByteArrayHttpMessageConverter : byte[] 데이터를 처리한다.
- 클래스 타입: byte[] , 미디어타입: */* ,
- 요청 예) @RequestBody byte[] data
- 응답 예) @ResponseBody return byte[] 쓰기 미디어타입 application/octet-stream
- StringHttpMessageConverter : String 문자로 데이터를 처리한다.
- 클래스 타입: String , 미디어타입: */*
- 요청 예) @RequestBody String data
- 응답 예) @ResponseBody return "ok" 쓰기 미디어타입 text/plain
- MappingJackson2HttpMessageConverter : application/json
- 클래스 타입: 객체 또는 HashMap , 미디어타입 application/json 관련
- 요청 예) @RequestBody HelloData data
- 응답 예) @ResponseBody return helloData 쓰기 미디어타입 application/json 관련
요청 매핑 핸들러 어뎁터 구조
ArgumentResolver
- HandlerMethodArgumentResolver 인데 줄여서 ArgumentResolver 라고 부른다.
- ArgumentResolver 의 supportsParameter() 를 호출해서 해당 파라미터를 지원하는지 체크하고,
- 지원하면 resolveArgument() 를 호출해서 실제 객체를 생성한다.
- 그리고 이렇게 생성된 객체가 컨트롤러 호출시 넘어가는 것이다
ReturnValueHandler
- HandlerMethodReturnValueHandler 를 줄여서 ReturnValueHandler 라 부른다.
- 응답 값을 변환하고 처리한다
'Spring > MVC' 카테고리의 다른 글
[MVC] MVC 구조 (0) | 2024.09.06 |
---|---|
[MVC] 프론트 컨트롤러 패턴 (0) | 2024.09.05 |
[MVC] MVC 패턴 (0) | 2024.09.05 |
[MVC] Servlet (0) | 2024.09.05 |