티스토리 뷰
728x90
스프링 웹 MVC(inflearn) - 백기선
SpringMVC 활용
- 핸들러 메소드 아규먼트 : 주로 요청 그 자체 또는 요청에 들어있는 정보를 받아오는데 사용
핸들러 메소드 아규먼트 설명 WebRequest
NativeWebRequest
ServletRequest(Response)
HttpServletRequest(Response)요청 또는 응답 자체에 접근이 가능한 API InputStream
Reader
OutputStream
Writer요청본문 (body)를 읽어오거나, 응답 본문을 쓸때 사용할 수 있는 API PushBuilder 스프링5에 생김.
HTTP/2 리소스 푸쉬에 사용
(브라우저에 필요한 이미지를 새로 요청하지 않고 서버에서 능동적으로 이미지를 푸쉬)HttpMethod GET, POST ... 등에 대한 정보 Locale
TimeZone
ZoneIdLocaleResolver가 분석한 요청의 Locale @PathVariable URI 템플릿 변수 읽을 때 사용 @MatrixVariable URI 경로 중에 키/값 쌍을 읽어 올 때 사용 @RequestParam 서블릿 요청 매개변수 값을 선언한 메소드 아규먼트 타입으로 변환해준다.
단순 타입인 경우에 이 애노테이션을 생략할 수 있다.@RequestHeader 요청 헤더 값을 선언한 메소드 아규먼트 타입으로 변환해준다. ... - 핸들러 메소드 리턴 : 주로 응답 또는모델을 랜더링할 뷰에 대한 정보를 제공하는데 사용
핸들러 메소드 리턴 설명 @ResponseBody 리턴 값을 HttpMessageConverter를 사용해 응답 본문으로 사용한다. HttpEntity
ResponseEntity응답 본문 뿐 아니라 헤더 정보까지, 전체 응답을 만들 때 사용한다. String ViewResolver를 사용해서 뷰를 찾을 때, 사용할 뷰 이름. View 암묵적인 모델 정보를 랜더링할 뷰 인스턴스 Map
Model(RequestToViewNameTranslator를 통해서) 암묵적으로 판단한 뷰 랜더링할 때 사용할 모델 정보 @ModelAttribute (RequestToViewNameTranslator를 통해서) 암묵적으로 판단한 뷰 랜더링할 때 사용할 모델 정보에 추가한다. 이 애노테이션은 생략할 수 있다.
핸들러 메소드 : URI 패턴
@PathVariable
- 요청 URI 패턴의 일부를 핸들러 메소드 아규먼트로 받는 방법
- 타입 변환 지원
- (기본)값이 반드시 있어야 한다.
- Optional 지원
@MatrixVariable
- 요청 URI 패턴에서 키/값 쌍의 데이터를 메소드 아규먼트로 받는 방법
- ex)
GET /events/1;name=keesun
- ex)
GET /events/id/1/name/keesun
- ex)
- 타입변환 지원
- (기본)값이 반드시 있어야 한다.
- Optional 지원
- 기본적으로 비활성화, 활성화를 위해서는 설정이 필요하다.
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { UrlPathHelper urlPathHelper = new UrlPathHelper(); urlPathHelper.setRemoveSemicolonContent(false); configurer.setUrlPathHelper(urlPathHelper); } }
- 요청 URI 패턴에서 키/값 쌍의 데이터를 메소드 아규먼트로 받는 방법
참고
- https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-typeco nversion
- https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-matrix -variables
핸들러 메소드 : 요청 매개변수(단순 타입)
- 요청 매개변수
- form 데이터
- query parameter
@RequestParam
- 요청 매개변수에 들어있는 단순 타입 데이터를 메소드 아규먼트로 받아올 수 있다.
- 값이 반드시 있어야 한다.
required=false
또는 Optional을 사용해서 부가적인 값으로 설정할 수 도 있다.
- String이 아닌 값들은 Conversion을 지원한다.
- Map<String, String> 또는 MultiValueMap<String, String> 을 사용해서 모든 요청 매개변수를 받아 올 수도 있다.
- 이 애노테이션은 생략할 수 있다.
참고
- https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann%20-requestparam
핸들러 메소드 : 폼 서브밋
- form을 보여줄 요청 처리
- GET /events/form
- 뷰 : events/form.html
- 모델 : "event", new Event()
- 타임리프
- @{}: URL 표현식
- ${}: variable 표현식
- *{}: selection 표현식
참고
핸들러 메소드 : @ModelAttribute
@ModelAttribute
- 여러 곳에 있는 단순 타입 데이터를 복합 타입 객체로 받아오거나, 해당 객체를 새로 만들 때 사용할 수 있다.
- 여러곳에서 오는 정보들로 객체를 바인딩 해준다.
- URI 패스, 요청매개변수, 세션 등
- 잘못된 타입이 들어오게 되면 BindingException 400 에러가 발생한다.
@ModelAttribute
바로 오른쪽에 BindingResult 타입의 아규먼트를 받으면 Exception을 BindingResult에 담고 요청은 통과가 된다. (BingdingResult의 상위객체인 Errors로도 가능하다.)public Event getEvent(@Valid @ModelAttribute Event event, BingdingResult bindingResult) { if (bindingResult.hasErrors()) { bingdingResult.getAllErrors().forEach(e -> { System.out.println(e.toString()); }); } return event; }
- 바인딩 이후 검증 작업을 추가하고 싶은 경우
@Valid
또는@Validated
어노테이션을 사용할 수 있다.@Validated
그룹 validation, Spring 제공- validation에 대한 에러도 BindingResult에 담아준다.
- 생략이 가능하다.
핸들러 메소드 : @Validated
- 스프링 MVC 핸들러 메소드 아규먼트에 사용할 수 있으며, validation group이라는 힌트를 사용할 수 있다.
@Valid
는 그룹을 지정할 방법이 없다.@Validated
는 스프링이 제공하는 어노테이션으로 그룹 클래스를 설정할 수 있다.- 기존 @Valid 기능을 포함 (똑같이 사용)
- 추가로 그룹 지정
- Controller
public Event getEvent(@Validated(Event.ValidateLimit.class) @ModelAttribute Event event, BingdingResult bindingResult) { if (bindingResult.hasErrors()) { bingdingResult.getAllErrors().forEach(e -> { System.out.println(e.toString()); }); } return event; }
public class Event { interface ValidateName {} interface ValidateLImit {} @NotBlank(groups = ValidateName.class) private String name; @Min(value = 0, groups = ValidateLimit.class) private Integer limit; }
핸들러 메소드 : 폼 서브밋 (에러처리)
- 바인딩 에러 발생 시, Model에 담기는 정보
- Event
- BindingResult.event
- 타임리프 사용 시, 바인딩 에러 보여주기
- https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#field-errors
<p th:if="${#fields.hasErrors('limit')}" th:errors="*{limit}">Incorrect date</p>
- Post/Redirect/Get 패턴
- https://en.wikipedia.org/wiki/Post/Redirect/Get
- Post 이후에 브라우저를 리프래시 하더라도 폼 서브밋이 발생하지 않도록 하는 패턴
- Post 이후 리프레쉬하는 경우 재요청을 하게 된다. 동일 Post 요청을 다시한다.
- 이것을 막기 위해 Post -> Redirect -> Get
- 리프레쉬를 하더라도 Get요청을 다시하도록 한다.
- 타임리프 목록 보여주기
<a th:href="@{/events/form}">Create New Event</a> <div th:unless="${#lists.isEmpty(eventList)}"> <ul th:each="event: ${eventList}"> <p th:text="${event.Name}">Event Name</p> </ul> </div>
핸들러 메소드 : @SessionAttributes
- 모델 정보를 HTTP 세션에 저장해주는 어노테이션
- HttpSession을 직접 사용할 수 도 있지만, 이 어노테이션에 설정한 이름에 해당하는 모델 정보를 자동으로 세션에 넣어준다.
@ModelAttribute
는 세션에 있는 데이터도 바인딩한다.- 여러화면에서 사용하는 객체를 공유해야하는 경우 사용한다.
@SessionAttributes("event") @Controller public class EventController { @GetMapping("/events/form") public Event getEvent(Model model) { Event newEvent = new Event(); newEvent.setLimit(50); model.addAttribute("event", newEvent); return "events/form"; } }
- SessionStatus를 사용해서 세션 처리 완료를 알려줄 수 있다.
- 폼 처리 끝나고 세션을 비울 때, 사용한다.
@SessionAttributes("event") @Controller public class EventController { public String getEvent(@Valid @ModelAttribute Event event, SessionStatus sessionStatus) { sessionStatus.setComplete(); return "redirect:/events/list"; } }
핸들러 메소드 : 멀티 폼 서브밋
- 세션을 사용해서 여러 폼에 걸쳐 데이터를 나눠 입력 받고 저장하기
- 이벤트 이름 입력받고
- 이벤트 제한 인원 입력받고
- 서브밋 -> 이벤트 목록으로
- 완려된 경우 세션에서 모델 객체 제거
- SessionStatus
핸들러메소드 : SessionAttribute
- HttpSession에 들어있는 값을 참조할 때 사용
- HttpSession을 사용할 때 보다 타입 컨버젼을 자동으로 지원
- HttpSession에 데이터를 넣고 빼고 싶은 경우에는 HttpSession을 사용할 것.
@SessionAttributes
와는 다르다.@SessionAttributes
는 해당 컨트롤러 내에서만 동작한다.@SessionAttribute
는 컨트롤러 밖(인터셉터 또는 필터 등)에서 만들어 준 세션에 접근할 때, 사용한다.
핸들러 메소드 : RedirectAttributes
- 리다이렉트 할 때 기본적으로 Model에 들어있는 원시타입 데이터는 URI query parameter에 추가된다.
- 스프링 부트에서는 이 기능이 기본적으로 비활성화 되어 있다.
- ignore-default-model-on-redirect 프로퍼티를 사용해서 활성화 할 수 있다.
- 스프링 부트에서는 이 기능이 기본적으로 비활성화 되어 있다.
- 원하는 값만 리다이렉트 할 때, 전달하고 싶다면 RedirectAttributes에 명시적으로 추가 할 수 있다.
- 리다이렉트 요청을 처리하는곳에서 query paramerter를 @RequestParam 또는 @ModelAttributes로 받을 수 있다.
- ex ) GET /events/list?name=aaaa 으로 리다이렉트 됨.
@GetMapping("/events/form-limit") public String getEvent(@Valid @ModelAttribute Event event, SessionStatus sessionStatus, RedirectAttributes attributes) { sessionStatus.setComplete(); attributes.addAttribute("name", event.getName()); return "redirect:/events/list"; }
핸들러 메소드 : Flash Attributes
- 주로 리다이렉트 시, 데이터를 전달할 때 사용한다.
- 데이터가 URI에 노출되지 않는다.
- 임의의 객체를 저장할 수 있다.
- 보통 HTTP 세션을 사용한다.
- 리다이렉트 하기전에 데이터를 HTTP 세션에 저장하고 리다이렉트 요청을 처리한 다음 그 즉시 제거한다. (1회성)
@GetMapping("/events/form-limit")public String getEvent(@Valid @ModelAttribute Event event, SessionStatus sessionStatus, RedirectAttributes attributes) { sessionStatus.setComplete(); attributes.addFlashAttribute("event", event); return "redirect:/events/list";}
핸들러 메소드 : MultipartFile
- 파일 업로드 시, 사용하는 메소드 아규먼트
- MultipartResolver 빈이 설정 되어야 사용할 수 있다.
- 빈이 없는 경우 DispatcherServelet 에서 설정하지 않는다.
- 즉, 빈이 없는경우 MultipartResolver를 사용하지 않는다.
- 스프링 부트를 사용하는 경우 MultipartResolver 빈의 등록을 자동설정이 해준다.
- 파일 업로드 관련 스프링 부트 설정
- MultipartAutoConfiguration
- MultipartProperties
- 파일 업로드 관련 스프링 부트 설정
- POST multipart/form-data 요청에 들어있는 파일을 참조할 수 있다.
- List 아규먼트로 여러파일을 참조할 수 도 있다.
- 파일 업로드 form
<form method="POST" enctype="multipart/form-data" action="#" th:action="@{/file}"> File:<input type="file" name="file"/> <input type="submit" value="Upload"/> </form>
- 파일 업로드 처리 핸들러
@PostMapping("/file") public String uploadFile(@RequestParam MultipartFile file, RedirectAttributes attributes) { //save String message = file.getOriginalFilename() + " is uploaded."; System.out.println(message); attributes.addFlashAttribute("message", message); return "redirect:/events/list"; }
- Test
- MockMultipartFile 사용
- name : multipartFile form의 파라미터 이름
- originalFileName : 파일의 이름
- contentType
- content
new MockMultipartFile("name", "originalFileName", "text/plain", "content".getBytes());
- MockMultipartFile 사용
핸들러 메소드 : ResponseEntity
- 파일 리소스를 읽어오는 방법
- 스프링 ResourceLoader 사용하기
Resource resource = resourceLoader.getResource("classpath:" + fileName);
- 파일 다운로드 응답 헤더에 설정할 내용
- Content-Disposition : 사용자가 해당 파일을 받을 때, 사용할 파일 이름
- Content-Type : 어떤 파일인가
- 파일의 종류 알아내기
- https://www.baeldung.com/java-file-mime-type
- http://tika.apache.org/
- tika core 의존성 추가 필요
- 파일의 종류 알아내기
- Content-Length : 얼마나 큰 파일 인가
@GetMapping("/file/{filename}") @ResponseBody public ResponseEntity<Resource> downloadFile(@PathVariable String filename) throws IOException { Resource resource = resourceLoader.getResource("classpath:" + filename); File file = resource.getFile(); Tika tika = new Tika(); String type = tika.detect(file); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachement; filename=\"" + resource.getFilename() + "\"") .header(HttpHeaders.CONTENT_TYPE, type) .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(file.length())) .body(resource); }
참고
핸들러 메소드 : @RequestBody & HttpEntity
@RequestBody
- 요청 본문(body)에 들어있는 데이터를 HttpMessageConverter를 통해 변환한 객체로 받아올 수 있다.
- @Valid 또는 @Validated를 사용해서 값을 검증할 수 있다.
- BindingResult 아규먼트를 사용해 코드로 바인딩 또는 검증 에러를 확인할 수 있다.
- HttpMessageConverter
- 스프링 MVC 설정 (WebMvcConfigurer)에서 설정할 수 있다.
WebMvcConfigurer.configureMessageConverters()
- 기본 메세지 컨버터를 대체 기본 컨버터들이 등록되지 않게됨으로 가급적 사용하지 않는것이 좋을듯하다.
WebMvcConfigurer.extendMessageConverters()
- 기본 메세지 컨버터에 추가
- 기본 컨버터가
WebMvcConfirationSupport.addDefaultHttpMessageConverters()
에 의해 등록된다.
- 스프링 MVC 설정 (WebMvcConfigurer)에서 설정할 수 있다.
- 요청헤더로부터 Content Type을 읽어서 핸들러 어댑터가 여러 컨버터중에 컨버팅할 수 있는 컨버터를 선택하여 컨버트를 한다.
- HttpEntity
@RequestBody
와 비슷하지만 추가적으로 요청 헤더 정보를 사용할 수 있다.
핸들러 메소드 @ResponseBody & ResponseEntity
@ResponseBody
- 데이터를 HttpMessageConverter를 사용해 응답 본문 메세지로 보낼 때 사용한다.
@RestController
사용 시, 자동으로 모든 핸들러 메소드에 적용된다.
- ResponseEntity
- 응답 헤더 상태 코드 본문을 직접 다루고 싶은 경우에 사용한다.
@JsonView
- ViewClass
public class JsonViewClass { interface Simple {} interface Complex extends Simple {}}
- Entity class
public class Entity { @JsonView(JsonView.Simple.class) private String name; @JsonView(JsonView.Simple.class) private int age; @JsonView(JsonView.Complex.class) private String etc;}
- 필드에 설정 시, 해당 값만 보여준다.
- 상속도 가능하다.
spring.jackson.mapper.default-view-inclusion=false
- 기본값
- true 로 변경 시, JsonView를 설정해도 다른 필드값이 보여진다.
728x90
'Spring > MVC' 카테고리의 다른 글
SpringMVC 활용 - 추가내용 (0) | 2021.10.11 |
---|---|
스프링 MVC 활용08 - HTTP 요청 맵핑하기 (0) | 2020.10.29 |
스프링 MVC 설정07 - 핸들러 인터셉터, 리소스 핸들러, HTTP 메세지 컨버터, 기타 설정 (0) | 2020.10.29 |
스프링 MVC 설정06 - 포매터 추가하기, 도메인 클래스 컨버터 자동 등록 (0) | 2020.10.29 |
스프링 MVC 설정05 - 스프링 부트에서 JSP 사용하기 (0) | 2020.10.29 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday