요청에 맞는 컨트롤러를 찾아서 호출하는 컨트롤러
스프링의 DispatcherServlet이 프런트 컨트롤러 패턴으로 구현되어 있다.
동작 순서
1.핸들러 조회: url에 맵핑된 핸들러(컨트로러)를 조회
2. 핸들러 어댑터 조회 및 실행
3. 핸들러 실행
4. ModelAndView 반환: 핸들러가 반환하는 정보를 ModelAndView로 변환 후 반환
5. 뷰 리졸버 호출
6. View 반환
7. 뷰 랜더링
@Controller
@RequestMapping
@Slf4j
@RestController
public class MappingController {
@RequestMapping("/hello-basic")
public String helloBasic() {
log.info("helloBasic");
return "ok";
}
@RestController: 반환 값을 Http 메시지 바디에 바로 입력
@RequestMapping: url 호출이 오면 이 메소드가 실행되도록 매핑
@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String data) {
log.info("mappingPath userId={}", data);
return "ok";
}
@PathVariable을 이용하여 매칭되는 부분을 편리하게 조회한다.
@PathVariable의 이름과 파라미터 이름이 같다면 생략 가능
@RestController
@RequestMapping("/mapping/users")
public class MappingClassController {
@GetMapping
public String users() {
return "get users";
}
@PostMapping
public String addUser() {
return "post user";
}
@GetMapping("/{userId}")
public String findUser(@PathVariable String userId) {
return "get userId=" + userId;
}
3가지 방법이 있다.
GET - 쿼리 파라미터
url파라미터에 데이터를 포함해서 전달
ex) http://localhost:8080/request-param?username=hello&age=20
Post - HTML form
메시지 바디에 쿼리 파리미터 형식으로 전달
ex)
POST /request-param ...
content-type: application/x-www-form-urlencoded
username=hello&age=20
@RequestParam
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam("username") String memberName,
@RequestParam("age") int memberAge) {
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
// 파라미터와 변수 이름이 같은 경우 생략 가능
@ResponseBody
@RequestMapping("/request-param-v3")
public String requestParamV3(
@RequestParam String username,
@RequestParam int age) {
log.info("username={}, age={}", username, age);
return "ok";
}
//파라미터를 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";
}
@RequestParam: 파라미터 이름으로 바인딩.
name() 속성이 파라미터 이름으로 사용
ex)
@RequestParam("username") String memberName
==
//서블릿 방식으로 조회
request.getParameter("username")
@ModelAttribute
요청 파라미터를 받아줄 객체를 자동으로 만들어준 후, 파라미터를 처리한다(set, get 등)
//HelloData
// 요청 파라미터를 바인딩 받을 객체
@Data
public class HelloData {
private String username;
private int age;
}
-본문-
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(),helloData.getAge());
return "ok";
}
// @ModelAttribute는 생략이 가능하다
//@RequestParam이랑 햇갈릴 수 있음
@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV2(HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
스프링은 @ModelAttribute가 있을 경우 다음을 실행한다.
단순 텍스트
@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("ok");
}
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("ok");
}
HttpEntity: http 헤더, 바디 정보를 편리하게 조회
RequestEntity, ResponseEntity
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
log.info("messageBody={}", messageBody);
return "ok";
}
json 조회시
@ResponseBody
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
HelloData data = objectMapper.readValue(messageBody, HelloData.class);
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
//한번에 객체로 변환
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
//HttpEntity 사용시
@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
return data;
}
@RequestBody: HTTP 메시지 정보를 편리하게 조회 가능
@ResponseBody: 응답 결과를 HTTP 메시지 바디에 직접 담아서 전달할 수 있다
3가지 방법이 있다
정적 리소스: 정적인 HTML 사용시
뷰 템플릿: 동적인 HTML 사용시
HTTP 메시지 이용: json 같은 데이터 전송시
//뷰 템플릿 호출 컨트롤러
@RequestMapping("/response-view-v1")
public ModelAndView responseViewV1() {
ModelAndView mav = new ModelAndView("response/hello").addObject("data", "hello!");
return mav;
}
//String 반환
@RequestMapping("/response-view-v2")
public String responseViewV2(Model model) {
model.addAttribute("data", "hello!!");
return "response/hello";
}
//void 반환 - 권장하지 않는 방법
@RequestMapping("/response/hello")
public void responseViewV3(Model model) {
model.addAttribute("data", "hello!!");
}
String으로 반환시
void 반환시
HTTP 메시지
//ResponseEntity는 http 메시지의 헤더, 바디 정보를 가지고 있다.
@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("ok", HttpStatus.OK);
}
//@ResponseBody를 이요하여 직접 데이터 전달
@ResponseBody
@GetMapping("/response-body-string-v3")
public String responseBodyV3() {
return "ok";
}
//ResponseEntity 를 반환한다. HTTP 메시지 컨버터를 통해서 JSON 형식으로 변환되어서 반환된다.
@ResponseStatus(HttpStatus.OK) // http 응답 코드를 설정
@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);
}
@RestController
HTTP API처럼 JSON 데이터를 HTTP 메시지
바디에서 직접 읽거나 쓰는 경우 HTTP 메시지 컨버터를 사용하면 편리하다.
다음의 경우 스프링은 메시지 컨버터를 적용한다
주요 메시지 컨버터
-Http 요청 데이터 읽기-
http 요청이 오고, 컨트롤러에서 @RequestBody , HttpEntity 파라미터를 사용하는 경우
-> 메시지 컨버터가 메시지를 읽을 수 있는지 확인한다
조건을 만족하는 경우 객체를 생성한 뒤 반환한다.
-HTTP 응답 데이터 생성-
컨트롤러에서 @ResponseBody , HttpEntity 로 값이 반환되는 경우
-> 메시지 컨버터가 메시지를 쓸 수 있는지 확인한다
조건 만족시 Http 응답 메시지 바디에 데이터를 생성
view에서 입력 폼 등을 이용해서 값을 받아올때,