2020-7-5 스프링 MVC(2)

Springboot

  • springboot 기본설정에서 dispatcherServlet의 doservice 디버거를 찍어보면 handlerMapping의 5개의 핸들러매핑이 등록되있다.
  • HandlerMapping : requestMappingHandlerMapping, BeanNameUrlHandlerMapping, RouterFunctinoMapping, SimpleUrlHandlerMapping, WelcomepageHandlerMapping
  • handlerAdopter
  • ViewSolver : ContentNegotiation이라는 viewResolver가 viewResolver이름에 대해서 처리
  • 자동설정에 대한 모든 설정은 spring.factories에 저장되어있다.
  • 스프링부트의 주관이 적용된 자동설정이 동작
    • JSP보단 Thymleaf선호
    • JSON지원
    • 정적리소스지원(welcomepage, favicon)
  • MVC커스터마이징
    • application.properties : ResourceProperties 클래스에 들어가면 설정관련된 메서드들이 있다. application.properties에 설정하기 위해서는 ResourceProperties 클래스를 잘봐라. => 가장 베스트
    • @Configuration + Implements WebMvcConfigure : 스프링부트의 MVC자동설정 + 추가설정
    • @Configuration + @EnableWebMvc : 스프링부트의 스프링MVC자동설정 사용하지 않음. 이때 implements WebMvcConfigure를 구현해야 편하다.

WebMvcConfigurer 설정

  • formatter

  • @RestController
    public class SampleController {
      @GetMapping("/hello/{name}")
      public String hello(@PathVariable String name) {
        return "hello" + name;
      }
    }
    
    @WebMvcTest
    @RunWith(SpringRunner.class)
    class SampleControllerTest {
      @Autowired
      private MockMvc mockMvc;
    
      @Test
      public void hello() throws Exception {
        this.mockMvc.perform(get("/hello/jimmy"))
          .andDo(print())
          .andExpect(content().string("hello jimmy"));
      }
    }
    
  • @PathVariable이 아니라 Formatter를 이용하면 객체를 문자열, 문자열 => 객체로 변환할 수 있다.

    • @RestController
      public class SampleController {
        @GetMapping("/hello/{name}")
        public String hello(@PathVariable("name") Person person) {
          return "hello" + person.getName();
        }
      }
      // springMVC가 name이 Person으로 아직 변환을 못해준다. Formatter를 써야된다.
      
    • formatter는 printer(객체 => 문자), parser(문자 => 객체)가 합쳐졌다.

    • public class PersonFormatter implements Formatter<Person> {
        @Override
        public Person parse(String s, Locale locale) throws ParseException {
          Person person = new Person();
          person.setName(s);
          return person;
        }
      
        @Override
        public String print(Person person, Locale locale) {
          return person.toString();
        }
      }
      
      public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addFormatters(FormatterRegistry registry) {
          registry.addFormatter(new PersonFormatter());
        }
      }
      
      @RestController
      public class SampleController {
        @GetMapping("/hello")
        public String hello(@RequestParam("name") Person person) {
          return "hello " + person.getName();
        }
      }
      
      @WebMvcTest
      @RunWith(SpringRunner.class)
      class SampleControllerTest {
        @Autowired
        private MockMvc mockMvc;
      
        @Test
        public void hello() throws Exception {
          this.mockMvc.perform(get("/hello")
                               .param("name", "jimmy"))
            .andDo(print())
            .andExpect(content().string("hello jimmy"));
        }
      }
      
    • 기존에 formatter를 등록하기 위해서는 WebMvcConfigurer를 구현해서 addFormatter를 쓴다.

    • 여기서 Converter도 등록할 수 있다.

    • 결론 : SpringBoot에서는 Formatter를 Bean으로 등록하면 알아서 등록해준다.

    • @WebMvc는 Web과 관련된 빈들만 등록해준다. 따라서 WebConfig를 지우고, PersonFormatter만 빈으로 등록하면 테스트가 깨진다. @SpringBootTest를 사용하면 모든 빈들을 다 등록해준다.
  • 도메인 클래스 컨버터

    • @SpringBootTest
      @AutoConfigureMockMvc
      @RunWith(SpringRunner.class)
      class SampleControllerTest {
        @Autowired
        private MockMvc mockMvc;
      
        @Autowired
        private PersonRepository personRepository;
      
        @Test
        public void hello() throws Exception {
          Person person = new Person("jimmy");
          personRepository.save(person);
      
          this.mockMvc.perform(get("/hello")
                               .param("id", "jimmy"))
            .andDo(print())
            .andExpect(content().string("hello jimmy"));
        }
      }
      
      public interface PersonRepository extends JpaRepository<Person, Long> {
      }
      
      
    • 스프링 데이터 JPA는 도메인 클래스 컨버터를 제공한다. Repository를 사용해 ID에 해당하는 엔티티를 읽는다.

    • JPA가 도메인 클래스 컨버터를 자동으로 등록해준다.

그밖의 설정

  • CORS설정 : CrossOrigin요청 처리 설정, 같은 도메인에서 온 요청이 아니더라도 처리를 허용하고 싶으면 쓴다.

  • 리턴값 핸들러설정 : 스프링 MVC가 제공하는 기본 리턴 값 핸들러외에 리턴핸들러를 추가하고 싶을때
  • ArgumentResolver : 스프링MVC가 제공하는 기본 argument resolver이외에 커스텀한 리졸버를 추가하고 싶을때
  • 뷰컨트롤러 : 단순하게 요청 URL을 특정 뷰로 연결하고 싶을때.
  • 비동기설정 : 비동기 요청 처리에 사용할 타임아웃이나 TaskExecutor를 사용할 수 있다.
  • 뷰리졸버 : 핸들러에서 리턴하는 뷰 이름에 해당하는 문자열을 view 인스턴스로 바꿔줄 뷰 리솔져를 설정
  • Content Negotiation : 요청 본문, 응답 본문을 어떤 MIME타입으로 보내야하는지 결정
Written on July 5, 2020