2020-7-26 스프링 MVC(9) ResponseEntity

ResponseEntity

파일 다운로드

  • 파일 리소스 읽는 방법 : 스프링 ResourceLoader사용하기
  • 파일 다운로드 응답 헤더에 설정할 내용
    • Content-Disposition : 사용자가 해당 파일을 받을 때 사용할 파일 이름
    • Content-Type : 어떤 파일인가
    • Content-Length : 얼마나 큰 파일인가
  • ResponseEntity
    • 응답 상태코드
    • 응답 헤더
    • 응답 본문

@RequestBody & HttpEntity

@RequestBody

  • 요청본문(body)에 들어있는 데이터를 를 HttpMessageConverter를 통해 변환한 객체로 받아올 수 있다.

  • @Valid, @Validated를 통해 값을 검증할 수 있다.

  • BindingResult아규먼트를 통해 코드로 바인딩 또는 검증에러를 확인할 수 있다.

  • @RestController
    @RequestMapping("/api/events")
    public class EventApi {
    
      @PostMapping
      public  Event createEvent(@RequestBody Event event) {
        // save
        return event;
      }
    }
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    public class EventApiTest {
    
      @Autowired
      private MockMvc mockMvc;
    
      @Autowired
      private ObjectMapper objectMapper;
    
      @Test
      public void createEvent() throws Exception {
        Event event = new Event();
        event.setName("api event");
        event.setLimit(100);
    
        String json = objectMapper.writeValueAsString(event);
    
    
        mockMvc.perform(post("/api/events")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(json))
          .andDo(print())
          .andExpect(status().isOk())
          .andExpect(jsonPath("name").value("api event"))
          .andExpect(jsonPath("limit").value(100));
      }
    }
    
    @RestController
    @RequestMapping("/api/events")
    public class EventApi {
      @PostMapping
      public  Event createEvent(@RequestBody @Valid Event event, BindingResult bindingResult) {
        if (bindingResult.hasErrors())
          bindingResult.getAllErrors().forEach(System.out::println);
        return event;
      }
    }
    
    • 요청이 올때 HttpMessageConverter를 통해 Event객체로 바꿔준다.
    • @EnableWebMvc를 Configuration을 추가.
    • HandlerAdaptor가 메세지 컨버터들을 사용한다.
    • mock의 content()가 http body를 의미

HttpMessageConverter

  • 스프링MVC 설정 (WebMvcConfigurer)에서 설정할 수 있다.
  • configureMessageConverters: 기본 메세지 컨버터 대체
  • extendMessageConverters: 메세지 컨버터 추가
  • 기본 컨버터
    • WebMvcConfigurationSupport.addDefaultHttpMessageConverters

HttpEntity

  • @RequestBody와 비슷하지만 추가적으로 요청 헤더 정보를 사용할 수 있다.

    • @RestController
      @RequestMapping("/api/events")
      public class EventApi {
      
        @PostMapping
        public  Event createEvent(HttpEntity<Event> request) {
          MediaType contentType = request.getHeaders().getContentType();
          System.out.println(contentType);
          return request.getBody();
        }
      }
      
      
    • @RequestBody에는 헤더정보가 없어서 HttpEntity<T>를 이용해서 요청에 해당하는 헤더와 바디정보를 함께 가져올 수 있다.

ResponseBody, ResponseEntity

ResponseBody

  • ResponseBody는 메서드레벨에서 붙인다
  • 데이터를 HttpMessageConverter를 사용해 응답 본문 메세지로 보낼때 사용
  • @RestController 사용시 자동으로 모든 핸들러 메서드에 적용된다.

ResponseEntity

  • 응답 헤더 상태 코드 본문을 직접 다루고 싶은 경우에 사용한다.

    • @Controller
      @RequestMapping("/api/events")
      public class EventApi {
      
        @PostMapping
        public ResponseEntity<Event> createEvent(@RequestBody @Valid Event event, BindingResult bindingResult) {
          if (bindingResult.hasErrors())
            return ResponseEntity.badRequest().build();
          return ResponseEntity.ok(event);
        }
      }
      
      

@ModelAttributes 또 다른 사용법

  • RequestMapping을 사용한 핸들러 메서드의 아규먼트에 사용하기

  • @Controller , @ControllerAdvice를 사용한 클래스에서 모델 정보를 초기화할 때 사용한다.

  • @RequestMapping과 같이 사용한다면 해당 메서드에서 리턴하는 객체를 모델에 넣어준다.

    • RequestToViewNameTranslator를 통해 ViewName을 전달
  • @ModelAttributes메서드

    • @ModelAttribute
      public void categories(Model model) {
        model.addAttribute("categories", Arrays.asList("study", "seminar"));
      }
      // 2nd
      @ModelAttribute("categories")
      public List<String> categories(Model model) {
        return Arrays.asList("study", "seminar");
      }
      //test message
      ModelAndView:
      View name = /events/list
        View = null
        Attribute = newEvent
        value = me.jimmy.springmvc.Event@7fdab70c
        errors = []
        Attribute = categories
        value = [study, seminar]
        Attribute = eventList
        value = [me.jimmy.springmvc.Event@25ad4f71]
      
      
    • 기본 카테고리 정보를 모든 뷰에서 참조할 수 있게된다. 테스트메세지를 보면 ModelAndView의 value에 값이 들어있는 것을 확인할 수 있다.

Databinder : @InitBinder

  • 특정 컨트롤러에서 바인딩 또는 검증 설정을 변경하고 싶을 때 사용

  • @InitBinder(“name”)을 주면 name에 해당하는 Model에 대해서만 적용된다.

  • @InitBinder
    public void initEventBinder(WebDataBinder webDataBinder) {
      webDataBinder.setDisallowedFields("id");
    }
    
  • 바인딩 설정 : webDataBinder.setDisallowedFileds(); => 받고 싶지 않은 필드를 필터링할 수 있다.

    • 폼으로 입력을 받아도 값에 설정한
  • 포매터설정 : webDataBinder.addCustomFormatter();

  • Validator설정 : webDataBinder.addValidators();

    • public class EventValidator implements Validator {
        @Override
        public boolean supports(Class<?> clazz) {
          return Event.class.isAssignableFrom(clazz);
        }
      
        @Override
        public void validate(Object target, Errors errors) {
          Event event = (Event)target;
          if (event.getName().equalsIgnoreCase("aaa"))
            errors.rejectValue("name", "wrongValue", "the value is not allowed");
        }
      }
      
      @Controller
      @SessionAttributes("event")
      public class EventController {
      
        @InitBinder
        public void initEventBinder(WebDataBinder webDataBinder) {
          webDataBinder.setDisallowedFields("id");
          webDataBinder.addValidators(new EventValidator());
        }
      }
      
    • custom한 Validator를 등록한다.

    • Validators를 구현하면 커스텀한 검증을 할 수 있다. 빈으로도 등록할 수 있다. 대신 명시적으로 검증해야한다.
  • 특정 모델객체만 바인딩 또는 Validator 설정을 적용하고 싶을때 : @InitBinder(“event”)
Written on July 26, 2020