스프링 MVC - 구조
- 핸들러 조회
- 핸들러 어댑터 조회
- 핸들러 어댑터 실행
- 핸들러 실행
- ModeelAndView 반환
- viewResolver 호출
- View반환
- render 호출
핸들러 매핑과 핸들러 어댑터
- HandlerMapping(ex.스프링 빈의 이름으로 핸들러를 찾을 수 있는 핸들러 매핑)
- RequestMappingHandlerMapping
- HandlerAdapter(핸들러를 실행할 수 있는 핸들러 어댑터 필요)
- RequestMappingHandlerAdapter
뷰 리졸버
- return new ModelAndView("new-form");
- BeanNameViewResolver: 빈 이름으로 뷰를 찾아서 반환
- InternalResourceViewResolver: JSP 처리할 수 있는 뷰 반환
스프링 MVC - 시작
- @RequestMapping 애노테이션을 사용하는 컨트롤러, 요청 정보 매핑(URL 호출)
- @Controller : 자동으로 스프링 빈으로 등록(@Component 컴포넌트 스캔 대상)
- ModelAndView : 모델과 뷰 정보 담아서 반환, mv.addObject("member", member)
스프링 MVC - 컨트롤러 통합
- 클래스 단위 -> 메서드 단위
- @RequestMapping 클래스 레벨과 메서드 레벨 조합
스프링 MVC - 실용적인 방식
- Model 도입
- ViewName 직접 반환
- @RequestParam 사용
- @RequestMapping(value = "/new-form", method = RequestMethod.GET) -> @GetMapping
스프링 MVC - 기본 기능
로깅
- 로그 선언
- private Logger log = LoggerFactory.getLogger(getClass());
- @Slf4j
- 로그 호출: log.info("hello")
- 로그 출력 포멧: 시간, 로그 레벨, 프로세스 ID, 쓰레드 명, 클래스명, 로그 메시지
- LEVEL: TRACE > DEBUG(개발 서버) > INFO(운영 서버) > WARN > ERROR
- application.properties
- logging.level.root=info(전체 로그 레벨)
- logging.level.hello.springmvc=debug(hello.springmvc 패키지와 하위 로그 레벨)
요청 매핑
@Controller: 반환 값 String-> 뷰 이름으로 인식
@RestController: HTTP 메시지 바디에 바로 입력
HTTP 메서드 매핑 축약: @GetMapping(value = "/mapping-get-v2")
PathVariable(경로 변수)
//@PathVariable 의 이름과 파라미터 이름이 같으면 생략 가능 @GetMapping("/mapping/{userId}") public String mappingPath(@PathVariable("userId") String userId) public String mappingPath(@PathVariable String userId) //PathVariable 사용 - 다중 @GetMapping("/mapping/users/{userId}/orders/{orderId}") public String mappingPath(@PathVariable String userId, @PathVariable Long orderId)
미디어 타입 조건 매핑
// HTTP 요청 Content-Type, consume @PostMapping(value = "/mapping-consume", consumes = "application/json") //HTTP 요청 Accept, produce @PostMapping(value = "/mapping-produce", produces = "text/html")
요청 매핑 - API
- 회원 목록 조회: GET /users
- 회원 등록: POST /users
- 회원 조회: GET /users/{userId}
- 회원 수정: PATCH /users/{userId}
- 회원 삭제: DELETE /users/{userId}
HTTP 요청 - 기본, 헤더 조회
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
)
HTTP 요청 파라미터
- 요청 파라미터(request parameter) 조회
- request.getParameter("username");
- public String requestParam(@RequestParam("username") String username)
- public String requestParam(@RequestParam String username)// 파라미터이름==변수이름 ("username") 생략가능
- public String requestParam(String username) //단순타입 @RequestParam 생략가능(required=false)
- @RequestParam(required = true, defaultValue = "guest") 기본값
- @RequestParam Map<String, Object> paramMap / @RequestParam MultiValueMap
- HTTP 요청 파라미터 - @ModelAttribute
- public String modelAttribute(@ModelAttribute Data Data)
- public String modelAttribute(Data Data)//@ModelAttribute 생략
HTTP 요청 메시지
HTTP 요청 메시지 - 단순 텍스트
1. ServletInputStream inputStream = request.getInputStream(); String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); response.getWriter().write("ok"); 2. public void requestBodyString(InputStream inputStream, Writer responseWriter) String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); responseWriter.write("ok"); 3. public HttpEntity<String> requestBodyString(HttpEntity<String> httpEntity) String messageBody = httpEntity.getBody(); return new HttpEntity<>("ok"); 4. @ResponseBody public String requestBodyString(@RequestBody String messageBody) return "ok";
HTTP 요청 메시지 - JSON
1. private ObjectMapper objectMapper = new ObjectMapper(); public void requestBodyJson(HttpServletRequest request, HttpServletResponse response) ServletInputStream inputStream = request.getInputStream(); String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); Data data = objectMapper.readValue(messageBody, Data.class); 2. @ResponseBody public String requestBodyJson(@RequestBody String messageBody) Data data = objectMapper.readValue(messageBody, Data.class); 3. @ResponseBody public String requestBodyJson(@RequestBody Data data) //@RequestBody 생략 불가(application/json)<->@ModelAttribute 4. @ResponseBody public String requestBodyJson(HttpEntity<Data> httpEntity) Data data = httpEntity.getBody(); @ResponseBody public String requestBodyJson(@RequestBody Data data) return data; //응답도 가능
- HttpEntity , @RequestBody -> HTTP 메시지 컨버터가 HTTP 메시지 바디의 내용을 문자나 객체 등으로 변환
### HTTP 응답
- 정적 리소스: 웹 브라우저에 정적인 HTML, css, js(src/main/resources/static)
- 뷰 템플릿: 웹 브라우저에 동적인 HTML(src/main/resources/templates)
- HTTP 메시지 사용: 데이터 전달
- 뷰 템플릿 호출
- ModelAndView mav = new ModelAndView("response/hello").addObject("data", "hello!");
return mav; - return "response/hello";
- Void 반환 요청 URL(/response/hello) 참고->templates/response/hello.html
- HTTP 응답 - HTTP API, 메시지 바디에 직접 입력
1. response.getWriter().write("ok"); 2. return new ResponseEntity<>("ok", HttpStatus.OK); 3. @ResponseBody return "ok"; 4. return new ResponseEntity<>(helloData, HttpStatus.OK); 5. @ResponseStatus(HttpStatus.OK) @ResponseBody return helloData; 6. @RestController=@Controller+@ResponseBody
HTTP 메시지 컨버터
- HTTP의 BODY에 문자 내용 직접 반환
- @ResponseBody 사용: viewResolver 대신 HttpMessageConverter 동작
- 대상 클래스 타입과 미디어 타입 체크
- 기본 문자처리: StringHttpMessageConverter(text/plain)
- 기본 객체처리: MappingJackson2HttpMessageConverter(application/json)
- byte[] 데이터 처리: ByteArrayHttpMessageConverter(application/octet-stream)
- HTTP 요청: @RequestBody , HttpEntity(RequestEntity)
- HTTP 응답: @ResponseBody , HttpEntity(ResponseEntity)
요청 매핑 헨들러 어뎁터 구조
- RequestMappingHandlerAdapter -> ArgumentResolver의 supportsParameter() -> HTTP 메시지 컨버터 사용 파라미터의 값(객체) 생성-> 컨트롤러(핸들러) -> ReturnValueHandler-> HTTP 메시지 컨버터 사용->응답 결과
스프링 MVC - 웹 페이지 만들기
상품 도메인 개발: Item(상품 객체), ItemRepository(상품 저장소)
//컨트롤러 @GetMapping public String items(Model model) { List<Item> items = itemRepository.findAll(); model.addAttribute("items", items); return "basic/items"; }
//타임리프(서버사이드 렌더링) <html xmlns:th="http://www.thymeleaf.org"> th:href="@{/css/bootstrap.min.css}" th:onclick="|location.href='@{/basic/items/add}'|" <tr th:each="item : ${items}"> <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td> <td><a href="item.html" th:href="@{|/basic/items/${item.id}|}"th:text="${item.itemName}">상품명</a></td> <td th:text="${item.price}">10000</td> <td th:text="${item.quantity}">10</td> </tr>
//상품 등록 컨트롤러 1. (@ModelAttribute("item") Item item, Model model) model.addAttribute("item", item); //자동 추가, 생략 가능 2. (@ModelAttribute Item item)// name 생략 가능, model.addAttribute("item", item); //자동 추가, 생략 가능, 첫글자 소문자 3. public String addItem(Item item) 전체 생략
### 리다이렉트
- 리다이렉트: return "redirect:/basic/items/{itemId}";
- PRG Post/Redirect/Get: 중복 등록 방지
- RedirectAttributes: URL 인코딩, pathVarible, 쿼리 파라미터 처리
public String addItemV6(Item item, RedirectAttributes redirectAttributes) {
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
타임리프
```
링크
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1
'스프링' 카테고리의 다른 글
검증 (0) | 2022.06.17 |
---|---|
타임리프 (0) | 2022.06.16 |
[스프링] MVC 프레임워크 (0) | 2022.06.09 |
[스프링] 서블릿, JSP, MVC 패턴 (0) | 2022.06.09 |
[스프링] 웹 애플리케이션 이해, 서블릿 (0) | 2022.06.09 |