스프링 부트 3.2.1 버전을 기준으로 작성됨
주의 : 스프링 부트 3 이상부터
URL 요청의 경우 /home
와 /home/
는 서로 다르게 매핑된다.
@RestController
: 반환 값을 HTTP 메시지 바디에 바로 입력 (뷰 x)
@ResponseBody
: View 조회 무시 및 HTTP 메시지 바디에 직접 해당 내용 입력
@RequestMapping()
: 기본적인 요청 매핑 , (배열 제공으로 다중 설정 가능)
ex) @RequestMapping({"/home", "/category"})
편리한 축약 애노테이션
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
error : 405 code
PathVariable (경로변수)
// 변수명이 같으면 생략 가능
// @PathVariable String userId
@GetMapping("/users/{userId}")
public String mappingPath(@PathVariable("userId") String data)
// 다중 사용
@GetMapping("/order/{userId}/{oderId}")
@PathVariable String userId, @PathVariable Long orderId
특정 조건 매핑
// 특정 파라미터 조건 매핑
// 파라미터가 맞아야 매핑됨
* 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")
// 미디어 타입 조건 매핑 - HTTP 요청 Content-Type, consume
* Content-Type 헤더 기반 추가 매핑 Media Type
* consumes="application/json"
* consumes="!application/json"
* consumes="application/*"
* consumes="*\/*"
* MediaType.APPLICATION_JSON_VALUE
@PostMapping(value = "/mapping-consume", consumes = "application/json")
error : 415 code
// 미디어 타입 조건 매핑 - HTTP 요청 Aceept, produce
* Accept 헤더 기반 Media Type
* produces = "text/html"
* produces = "!text/html"
* produces = "text/*"
* produces = "*\/*"
@PostMapping(value = "/mapping-produce", produces = "text/html")
error : 406 code
같은 url에 method만 다르게 하여 요청을 처리하는 방식을 택하자
@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로 찍어보면 알 수 있다.
host
* 특정 HTTP 헤더를 조회
* 속성
* 필수 값 여부: required
* 기본 값 속성: defaultValue
cookie
* 특정 쿠키를 조회
* 속성
* 필수 값 여부: required
* 기본 값: defaultValue
MultiValueMap
* 하나의 키에 여러 값을 받기 가능
* HTTP header, HTTP 쿼리 파라미터와 같이 하나의 키에 여러 값을 받을 때 사용
* ex) keyA=value1&keyA=value2
/*
MultiValueMap<String, String> map = new LinkedMultiValueMap();
map.add("keyA", "value1");
map.add("keyA", "value2");
*/
쿼리 파라미터
/home?name=kim&age=10
HTML Form
V1 : HttpServletRequest or Response : getParameter()
V2 : @RequestParam("파라미터 명") 자료형 변수
V3 : @RequestParam 자료형 변수 (파라미터 이름 == 변수 이름)
V4 : 자료형 변수 (String, int, Integer 등 단순 타입이면 @RequestParam 생략 가능)
주의
@RequestParam
애노테이션을 생략하면 스프링 MVC는 내부에서 required=false
를 적용
V3을 사용하도록 하자
파라미터 필수 여부
@RequestParam(required = true) String username
주의
defaultValue
사용기본 값 적용
@RequestParam(required = true, defaultValue = "guest") String username,
@RequestParam(required = false, defaultValue = "-1") int age
파라미터 Map으로 조회
@RequestParam Map<String, Object> paramMap
MultiValueMap<String, Object> paramMap
paramMap.get("파라미터 이름")
요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 바로 값을 넣는 방법
@Data // lombok (@getter,setter,toString... 등등 자동으로 적용)
public class Student {
private String name;
private int age;
}
public String modelAttrV1(@ModelAttribute Student student) {
student.getName(); // 프로퍼티 접근
}
* @ModelAttribute 생략 가능
* String, int 같은 단순 타입 : @RequestParam
* argument resolver 지정 타입 외 : @ModelAttribute
public String modelAttrV2(Student student) {
student.getName(); // 프로퍼티 접근
}
바인딩 오류
숫자를 받는 곳에 문자를 넣으면 BindException
이 발생 -> 검증
여기서는 우선 단순 텍스트
HTTP 메시지 바디를 통해 데이터가 직접 넘어오는 경우는 @RequestParam
,@ModelAttribute
를 사용 불가
V1 : InputStream 으로 직접 읽기
V2 : Input, Output 스트림, Reader 사용
V3
* HttpEntity: HTTP header, body 정보를 편리하게 조회
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
* - 응답에서도 HttpEntity 사용 가능
* - 메시지 바디 정보 직접 반환(view 조회X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("ok");
}
// HTTP 상태 코드 설정 가능, 응답에서 사용
// return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED)
V4
* @RequestBody
* - 메시지 바디 정보를 직접 조회(@RequestParam X, @ModelAttribute X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*
* @ResponseBody
* - 메시지 바디 정보 직접 반환(view 조회X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
log.info("messageBody={}", messageBody);
return "ok";
}
// 헤더 정보가 필요하다면
// HttpEntity || @RequestHeader 를 사용
V1
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);
log.info("messageBody={}", messageBody);
// 문자로 된 json 데이터를 Jackson 라이브러리인 objectMapper 사용하여 json을 객체로 변환
HelloData data = objectMapper.readValue(messageBody, HelloData.class);
log.info("username={}, age={}", data.getUsername(), data.getAge());
V2
// 메시지에서 데이터 꺼내고 messageBody에 저장
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
// 마찬가지로 objectMapper로 자바 객체 변환
HelloData data = objectMapper.readValue(messageBody, HelloData.class);
log.info("username={}, age={}", data.getUsername(), data.getAge());
V3
/* @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림)
* HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter (content-type: application/json)
*/
public String requestBodyJsonV3(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
V4
public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) {
HelloData data = httpEntity.getBody();
log.info("username={}, age={}", data.getUsername(), data.getAge());
V5
// 객체 반환 -> JSON 응답
public HelloData requestBodyJsonV5(@RequestBody HelloData data) {
return data;
주의
HTTP 요청시에 content-type이 application/json인지 확인 -> JSON을 처리할 수 있는 HTTP 메시지 컨버터가 실행
서버 응답 데이터
정적 리소스
/static
, /public
, /resources
, /META-INF/resources
뷰 템플릿
src/main/resources/templates
String 반환
void 반환
Thymeleaf 스프링 부트 설정
application.properties
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
String (단순 텍스트)
// V1
public void v1(HttpServletResponse response) throws IOEception {
response.getWriter().write("ok);
}
// V2
public ResponseEntity<String> v2() {
return new ResponseEntity<>("ok", HttpStatus.OK);
}
// V3
@ResponseBody
public String responseBodyV3() {
return "ok";
}
Json
// V1
public ResponseEntity<HelloData> V1() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return new ResponseEntity<>(helloData, HttpStatus.OK);
}
// V2
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public HelloData V2() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(20);
return helloData;
}
스프링 MVC는 다음의 경우에 HTTP 메시지 컨버터를 적용한다.
@RequestBody
, HttpEntity(RequestEntity)
@ResponseBody
, HttpEntity(ResponseEntity)
RequestMappingHandlerAdapter 동작 방식
HTTP 메시지 컨버터 위치
더 자세한 내용은 강의와 교재를 참고
🔖 학습내용 출처