HTTP 요청 - 기본, 헤더 조회
package hello.springmvc.basic.request;
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
@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";
}
}
HttpMethod : HTTP메서드를 조회한다.
Locale: Locale 정보를 조회한다.
@RequestHeader MultiValueMap<String, String> : 모든 HTTP 헤더를 MultiValueMap 형식으로 조회한다.
@RequestHeader("host") 필수 값 : required , 기본 값 속성: defaultValue : 특정 HTTP 헤더를 조회한다.
@CookieValue 필수 값: required , 기본 값 : defaultValue : 특정 쿠키를 조회한다.
MultiValueMap
MAP과 유사한데 , 하나의 키에 여러 값을 받을 수 있다.
HTTP header, HTTP 쿼리 파라미터와 같이 하나의 키에 여러 값을 받을 때 사용한다.
ex) keyA=value1&keyA=value2
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("keyA","value1");
map.add("keyA","value2");
List<String> values = map.get("keyA");
HTTP 요청 파라미터 - 쿼리 파라미터, HTML Form
GET - 쿼리 파라미터
ex) url?username=hello&age=20
메시지 바디없이 , URL의 쿼리 파라미터에 데이터를 포함해서 전달
POST - HTML Form
content-type: application/x-www-form-urlencoded
메시지 바디에 쿼리 파라미터 형식으로 전달 username=hello&age=20
HTTP message body에 데이터를 직접 담아서 요청
HTTP API에서 주로 사용, JSON , XML, TEXT
HTTP 요청 파라미터 - @RequestParam
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(@RequestParam("username") String username,
@RequestParam("age") int age) {
log.info("username={}, age={}", username, age);
return "ok";
}
@RequestParam : 파라미터 이름으로 바인딩
@ResponseBody : View 조회를 무시하고 , HTTP message body에 직접 해당 내용 입력
@RequestParam("username") String memberName => request.getParameter("username")
HTTP 파라미터 이름이 변수 이름과 같으면 @RequestParam(name="xx") 생략 가능하다
=> @RequestParam String username
String , int , Integer 등의 단순 타입이면 @RequestParam 도 생략이 가능하다
@RequestParam 애노테이션을 생략하면 스프링 MVC 내부에서 required=false를 적용한다.
파라미터 필수 여부 - requestParamRequired
@ResponseBody
@RequestMapping("/request-param-required")
public String requestParamRequired(@RequestParam(required = true) String username,
@RequestParam(required = false) Integer age) {
log.info("username={}, age={}", username, age);
return "ok";
}
required = true : 파라미터가 필수이다. url에 파라미터가 없으면 400 예외가 발생한다.
변수 age 가 int 형 이면 required 가 false 여도 에러가 났을 것이다.
int에는 null을 받을 수 없기 때문에 파라미터가 없으면 null 값이 들어와 500예외가 발생한다. 그래서 age를 Integer로 바꿔줬다.
기본 값 적용 - requestParamDefault
@ResponseBody
@RequestMapping("/request-param-default")
public String requestParamDefault(@RequestParam(required = true, defaultValue = "guest") String username,
@RequestParam(required = false, defaultValue = "-1") Integer age) {
log.info("username={}, age={}", username, age);
return "ok";
}
파라미터에 값이 없는 경우 defaultValue 를 사용하면 기본 값을 적용할 수 있다.
이미 기본 값이 있기 때문에 required는 의미가 없다
파라미터를 Map으로 조회하기 - requestParamMap
@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";
}
@RequestParam Map => Map(key=value)
파라미터 값이 1개가 확실하다면 Map을 사용해도 되지만 그렇지 않다면 MultiValueMap을 사용하자.
HTTP 요청 파라미터 - @ModelAttribute
개발을 할때 요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주어야한다.
스프링은 이 과정을 완전히 자동화 해주는 @ModelAttribute기능을 제공한다.
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
log.info("username={} , age={}" , helloData.getUsername(),helloData.getAge());
log.info("helloData={}" , helloData);
return "ok";
}
스프링 MVC는 @ModelAttribute가 있으면 다음을 실행한다.
HelloData 객체를 생성한다.
요청 파라미터 이름으로 HelloData 객체의 프로퍼티를 찾는다. 해당 프로퍼티의 setter 를 호출해서
파라미터의 값을 입력한다.
객체에 getUsername() , setUsername() 메서드가 있으면, 이 객체는 username이라는 프로퍼티를 가지고 있다.
@ModelAttribute 는 생략 할 수있다.
String, int, Integer 같은 단순 타입 = @RequestParam
나머지 = @ModelAttribute
HTTP 요청 메시지 - 단순 텍스트
HTTP 메시지 바디를 통해 데이터가 직접 데이터가 넘어오는 경우는 @RequestParam , @ModelAttribute를 사용할 수 없다.
@PostMapping("/request-body-string-v1")
public void requestBodyStringV1(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("ok");
}
HTTP 메시지 바디의 데이터를 InputStream 을 사용해서 직접 읽을 수 있다.
@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("ok");
}
InputStream(Reader) : HTTP 요청 메시지 바디의 내용을 직접 조회
OutputStream(Writer) : HTTP 응답 메시지의 바디에 직접 결과 출력
@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<>("ok");
}
HttpEntity : HTTP header, body 정보를 편리하게 조회
-> 메시지 바디 정보를 직접 조회
HttpEntity는 응답에도 사용 가능
RequestEntity : 요청에서 사용
ResponseEntity : HTTP 상태코드 설정 가능 , 응답에서 사용
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) throws IOException {
log.info("messageBody={}", messageBody);
return "ok";
}
@RequestBody
@RequestBody를 사용하면 HTTP 메시지 바디 정보를 편리하게 조회 할 수 있다.
헤더정보가 필요하다면 HttpEntity , @RequestHeader 를 사용하면 된다.
HTTP 요청 메시지 - JSON
@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData data){
log.info("username={},age={}", data.getUsername(), data.getAge());
return data;
}
@RequestBody 에 직접 만든 객체를 지정할 수 있다.
@RequestBody , @HttpEntity 를 사용하면 HTTP 메시지 컨버터와 HTTP 메시지 바디의 내용을 우리가 원하는 객체나 문자 등으로 변환해준다.
@ResponseBody 를 사용하면 해당 객체를 HTTP 메시지 바디에 직접 넣어 줄 수 있다.
HTTP 응답 - 정적 리소스, 뷰 템플릿
스프링에서 응답 데이터를 만드는 방법은 3가지이다.
1. 정적 리소스
ex) 웹 브라우저에 정적인 HTML , css, js 을 제공할 때는 정적 리소스를 사용한다.
2. 뷰 템플릿 사용
ex) 웹 브라우저에 동적인 HTML을 제공할 때는 뷰 템플릿을 사용한다.
3. HTTP 메시지 사용
ex) HTTP API를 제공하는 경우에는 HTTP 메시지 바디에 JSON 같은 형식으로 데이터를 실어 보낸다.
정적 리소스
스프링 부트는 클래스패스의 다음 디렉토리에 있는 정적 리소스를 제공한다.
/static , /public , /resources , /META-INF/resources
정적 리소스 경로
src/main/resources/static
ex) src/main/resources/static/basic/hello-form.html
-> 웹브라우저에 다음과 같이 실행하면 된다
http://localhost:8080/basic/hello-form.html
뷰 템플릿
뷰 템플릿 경로
src/main/resources/templates
@RequestMapping("/response-view-v1")
public ModelAndView responseViewV1() {
ModelAndView mav = new ModelAndView("response/hello");
mav.addObject("data","hello!");
return mav;
}
@RequestMapping("/response-view-v2")
public String responseViewV2(Model model) {
model.addAttribute("data","hello!");
return "response/hello";
}
@RequestMapping("/response/hello")
public void responseViewV3(Model model) {
model.addAttribute("data", "hello!!");
}
@ResponseBody가 없으면 response/hello로 뷰 리졸버가 실행되어서 뷰를 찾고, 렌더링 한다.
Void를 반환하는 경우
@Controller를 사용하고, HttpServletResponse, OutputStream(Writer) 같은 HTTP 메시지 바디를 처리하는 파라미터가 없으면 요청 URL을 참고해서 논리 뷰 이름으로 사용한다.
요청 URL : /response/hello
실행: templates/response/hello.html
HTTP 응답 - HTTP API, 메시지 바디에 직접 입력
@GetMapping("/response-body-string-v1")
public void responseBodyV1(HttpServletResponse response) throws IOException {
response.getWriter().write("ok");
}
@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2(HttpServletResponse response) throws IOException {
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;
}
responseBodyV2
ResponseEntity 엔티티는 HttpEntity를 상속 받았는데, HttpEntity는 HTTP 메시지의 헤더, 바디정보를 가지고 있다.
ResponseEntity는 여기에 더해서 HTTP 응답 코드를 설정할 수 있다.
responseBodyJsonV2
@ResponseStatus(HttpStatus.OK) 애노테이션을 사용하면 응답 코드도 설정할 수 있다.
@RestController
@Controller 대신 @RestController 애노테이션을 사용하면, 해당 컨트롤러에 모두 @ResponseBody가 적용되는 효과가 있다.
클래스 레벨에 @ResponseBody를 두면 전체에 메서드에 적용된다.
출처
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1
'SPRING' 카테고리의 다른 글
김영한 - 스프링 MVC 2편 - 백엔드 웹 개발 핵심 기술 1일차 (0) | 2022.01.10 |
---|---|
김영한 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 7일차 (0) | 2022.01.07 |
김영한 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 5일차 (0) | 2022.01.04 |
김영한 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 4일차 (0) | 2022.01.03 |
김영한 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 3일차 (0) | 2021.12.30 |