https://www.inflearn.com/course/%EC%9B%B9-mvc
ㅁ 스프링 MVC 활용
ㅇ 요청 맵핑하기 - HTTP Method , URI 패턴 맵핑
- @GetMapping이 아닌 @RequestMapping으로 받으면 모든 method로 허용
> method={} 형식으로 허용되는거 설정 가능
- 5번대 에러 서버 잘못
- 4번대 에러 요청이 잘못됨
- get은 post와 달리 캐싱을 할 수 있음, idempotent (멱등성)
- post는 put과 차이, put patch 차이
- 컨트롤러 위에 @RequestMapping을 달면 모든 핸들러에 해당 옵션 추가
> get 요청 만 받기 등
- ** 하면 어떤 패스든 가능, * 하나면 한개의 패스만 가능
- 동일한 패스의 맵핑이 있으면, 코드 순서상 위에 있는것이 맵핑이 됨
- 핸들러 테스트도 가능
.andExpect(handler().handlerType(SampleController.class))
.andExpect(handler().methodName("hello"))
- 스프링 MVC에서는 /hello로 맵핑할 경우, /hello.* 로 요청도 들어오게됨 (URI 확장자 맵핑 지원 )
> 스프링 부트에서는 그렇지않음
>> rfd (reflected file download attack) 방지를 위해 막아둠
- 여러 형식의 요청을 받아야할 경우 (파일 다운로드 등) - URI 확장자 맵핑은 하지않는게 좋음
1. content type 사용
2. parameter 사용
ㅇ 요청 맵핑하기 - 컨텐츠 타입 맵핑
- header에서 json 타입을 요청한 것만 받기 : @RequestMapping(value = "/hello", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) ( 415 에러 - not Supported media type )
- produces = MediaType.TEXT_PLAIN_VALUE 로 요청하는 응답값을 보고 맵핑할 수도 있음 (406 에러 - not acceptable)
- consumes와 produces는 클래스에 선언한 @RequestMapping에 사용한 것과 조합되지 않고, 메소드에 사용한 RequestMapping의 설정으로 덮어쓴다.
ㅇ 요청 맵핑하기 - 헤더와 파라미터 맵핑
- headers = HttpHeaders.ACCEPT_LANGUAGE 로 헤더에 포함된 파라미터 요청만 매핑됨 ( ALLOW 헤더는 제외 )
> not일 경우 : headers = "!" + HttpHeaders.FROM
> 값이 일치 : headers = HttpHeaders.FROM + "=" + "localhost"
> param 존재 및 값 일치 : params = "name=spring"
ㅇ 요청 맵핑하기 - HEAD와 OPTIONS 요청 처리
- 우리가 구현하지 않아도 스프링 웹 MVC에서 HTTP Method 로 HEAD와 OPTION을 설정함
- HEAD 요청은 GET과 비슷하나, response 의 body를 받지 않음
- OPTION 요청은 서버 또는 특정 리소스가 제공하는 기능을 확인할 수 있음 (METHOD 등)
> controller가 응답하지는 않음
- hasItems, containsString 사용 (순서 맞게 하기 위해 )
.andExpect(header().stringValues(HttpHeaders.ALLOW,
hasItems(
containsString("GET"),
containsString("POST"),
containsString("HEAD"),
containsString("OPTIONS")
)))
ㅇ 요청 맵핑하기 - 커스텀 애노테이션
- Composed Annotaion : 다른 애노테이션을 조합해서 만든것
- Meta Annotation : 애노테이션 위에 사용할 수 있는 에노테이션
- @Retention : 해당 애노테이션 정보를 언제까지 유지할 것인가
> 자바의 애노테이션 : 기본값은 .class => 컴파일 후 런타임시 로드 후 사라지게됨 (로드할때)
구동된 이후 유지하기 위해서는 런타임으로 설정 @Retention(RetentionPolicy.RUNTIME)
ㅇ 핸들러 메소드 - 아규먼트와 리턴 타입
- NativeWebRequest, WebRequest : 스프링이 제공하는거라 servlet api를 감싸는것
- Servlet시 구현한 HttpServletRequest , HttpServletResponse도 컨트롤러에서 파라미터로 가져올 수 있음
- pushbuilder : http2.0 리소스 푸쉬에 사용
- ResponseEntity: RESTAPI 응답으로 좋음
ㅇ 핸들러 메소드 - URI 패턴
- @PathVariable(required=false)
- Matrixvariable => WebConfig에 아래 구현
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
ㅇ 핸들러 메소드 - 요청 매개변수 (단순 타입) & 폼 서브밋 & modelAttribute & Validated
- mockMvc는 파라미터로만 보낼 수 있음 (form은 어려움)
- @{} : URL 표현식
- ${} : variable 표현식
- *{} : selection 표현식 : scope 안에 특정 객체의 값을 선택해줌
- view(), model() 도 테스트 가능
.andExpect(view().name("/events/form"))
.andExpect(model().attributeExists("event"))
- RequestParam을 생략할수도 있음
- parameter로 보내는 값을 @ModelAttribute를 통해 바로 객체로 converting 할 수 있다.
> binding 할때 type 에러가 발생할 수 있다.
>> bindingResult 라는 변수로 따로 처리해줄 수 있음 (잘못된 입력값에 대한 처리 )
- @Valid라는 애노테이션으로 값을 검증할 수 있음 (ex ) @Min(0) )
> @Valid 는 그룹화하여 검증할 수 없음
> @Validated는 그걸 보완함 (기초적인 기능은 동일 )
ㅇ 핸들러 메소드 - 폼 서브밋 에러 처리 & SessionAttributes & @SessionAttributes
- save 후 , redirect 로 조회 페이지로 보내기
> refresh 해도 form 중복 submit을 안함\
> Post -> redirect -> get 패턴
- HttpSession를 parameter로 사용해서 세션에 객체를 넣을 수도 있음
> @SessionAttributes("event") 로 세션에 객체가 자동을 저장됨
> 세션에 값을 왜 담을까? : 여러 화면에서 값을 입력해야할때가 있음, 이때 세션에 객체를 넣어서 다음에 계속 담아 submit함
> 처리 후 sessionStatus.setComplete() 를 통해 비움
- @SessionAttributes 와 @SessionAttribute는 다른것임
> SessionAttribute는 파라미터로 하나의 값을 가져옴
> SessionAttributes는 위에 적었듯이 객체를 세션에 담음
- ModelAttribute 로 Session에 담긴 값도 객체 parameter로 받음
ㅇ 핸들러 메소드 - RedirectAttributes
- redirect 할때, model에 값을 담아주면 redirect url 뒤에 parameter로 넘어감
> boot는 이 기능이 꺼져있음
>> spring.mvc.ignore-default-model-on-redirect=false 로 켜야함
>> 일부만 보내고 싶으면, redirectAttributes 사용
>> redirect 되는곳에서 RequestParam으로 받아서 처리할 수 있다
- ModelAttribute로 parameter를 받을 수 있으나, session과 겹칠수도 잇기때문에, ModelAttirbute("new event") 와 같이 session 객체와 다르게 설정
- redirectAttributes 사용을 위해서는 모두 String parameter로 변해야함
ㅇ 핸들러 메소드 - Flash Attributes
- 데이터가 url에 노출되지 않는다.
- httpsession을 통해 전달됨
- model에 자동으로 들어가짐
- redirectAttributes에 addFlashAttributes 하여, 객체를 전달할 수 있음 (심지어 key, value(ojbect) 형식으로, 받는쪽에서 modelAttribute로 바로 받을수 있음
ㅇ 핸들러 메소드 - MultipartFile & 파일 다운로드
- 기본 디스페쳐 서블릿 전략은 multipart resolver가 없음
- 스프링 부트는 있음
> 우리가 설정하지 않더라도 파일을 업로드 할 수 있음
- @SpringBootTest는 모든 bean을 등록해주지만, MockMVC는 가져오지 않음
> @AutoConfigureMockMvc로 가져와주자
- Response Entity를 만들어서 파일을 다운로드 하게 해줌
> 헤더를 설정하고, 바디에 Resource로 파일 리소스를 가져와 넣어주면 됨
> Response Entity로 만들어 리턴하면 응답이나 우리가 원하는걸 커스터마이징 할 수 있다.
- tika를 통해 헤더에 파일 타입을 자동으로 넣어줌
ㅇ 핸들러 메소드 - @RequestBody & HttpEntity
- 요청의 바디에 들어있는 데이터를 HttpMessageConverter를 통해 변환한 객체로 받는것
- @EnableWebMvc를 붙이는 순간,
- 핸들러어댑터가 메시지 컨버터를 사용하며, 메소드 아규먼트를 resolve 함
> 보통 헤더에 바디에 들어있는 데이터의 타입을 기입하여 들어옴
> 이것을 참고하여 핸들러어댑터가 변환시켜줌
- ObjectMapper는 jackson이 제공하는건데, json <-> 스트링 변환 할 수있음
> 자동 제공 및 빈으로 등록시켜줌
- HttpEntity<Event> 로 변환할 객체를 설정할 수 있다.
> 헤더 정보를 확인할 수도 있다.
>> HttpEntity<Event> request => request.getHeader().getContentType();
> @RequestBody는 Body만 가져온다.
> extendMessageConverter를 통해 없는 converter는 추가
ㅇ 핸들러 메소드 - @ResponseBody & ResponseEntity
- @ResponseBody : 응답본문에 있는 메시지로 메소드의 return 타입을 담아줌 (httpMessageConverter 사용)
> 기계한테는 json으로 보여주는게 유리, 사람한테는 html
- @RestController는 @ResponseBody 포함함
- ReponseEntity로 응답을 커스터마이징 할 수 있다.
> 에러시 메시지 포함 등
> ok(), badRequest().build() 등 자주쓰는건 이미 있음
ㅇ 모델 : @ModelAttribute 또 다른 사용법
- List.of는 자바 9 이상부터 가능
- 모든 모델에 공통적인 값 설정 가능, 모델 정보 초기화
- @RequestMapping or @GetMapping과 같이 사용하면 해당 메소드에서 리턴하는 객체를 모델에 넣어준다.
> RequestToViewNameTranslator가 요청 동일한 view로 리턴해준다.
ㅇ DataBinder : @InitBinder
- 아래와 같이 데이터 바인더 설정
@InitBinder("Event")
public void initEventBinder(WebDataBinder webDataBinder){
// 아이디 필드를 데이터바인딩시 받지 않음
webDataBinder.setDisallowedFields("id");
// 유효값 검증을 위한 커스터마이징 validator 설정
webDataBinder.addValidators(new EventValidator());
}
- @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) 로 LocalDate를 받을때 설정할 수 있다.
ㅇ 예외 처리 핸들러 @ExceptionHandler
- RuntimeException 을 상속할 경우, try catch 등이 필요없음
- 커스터마이징한 에러를 받아 모델에 담아 특정페이지로 return 할 수 있음
- ResponseEntity로 return 하여, 에러 메시지와 코드를 담아 리턴 함 (REST API 형식)
ㅇ 전역 컨트롤러 @ControllerAdvice
- ExceptionHandler와 같이, 모든 컨트롤러에 공통적으로 처리하고 싶은값들을 설정함
- @ControllerAdvice(assignableTypes = {EventController.class, EventApi.class})
와 같이 특정 컨트롤러에만 설정도 가능
- @RestControllerAdvice = @ControllerAdvice + @ResponseBody
'Spring' 카테고리의 다른 글
[Spring] 스프링 기반 REST API 개발 - 2 (0) | 2021.08.03 |
---|---|
[Spring] 스프링 기반 REST API 개발 - 1 (0) | 2021.08.03 |
[Spring] 스프링 웹 MVC - 2 (0) | 2021.07.28 |
[Spring] 스프링 웹 MVC - 1 (0) | 2021.07.27 |
[Spring] 스프링 데이터 JPA - 4 (0) | 2021.07.26 |