스프링 MVC 설정(6) : WebMvcConfigure - Formatter

de_sj_awa·2021년 6월 27일
0

7. WebMvcConfigure - Formatter

컨트롤러

@RestController
public class SampleController {

    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}

테스트 코드

@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void hello() throws Exception{
        this.mockMvc.perform(get("/hello")
               .andDo(print())
               .andExpect(content().string("hello"));
    }
}

그런데 이 요청을 다음과 같이 보낸다고 해보자.

@RestController
public class SampleController {
    
    @GetMapping("/hello/{name}")
    public String hello(@PathVariable("name") String name){
        return "hello " + name();
    }
}
@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void hello() throws Exception{
        this.mockMvc.perform(get("/hello")
                .param("name", "spring"))
                .andDo(print())
                .andExpect(content().string("hello spring"));
    }

Formatter

  • Printer: 해당 객체를 (Locale 정보를 참고하여) 문자열로 어떻게 출력할 것인가
  • Parser: 어떤 문자열을 (Locale 정보를 참고하여) 객체로 어떻게 변환할 것인가

Formatter를 사용하면 문자열을 객체로 받을 수 있다.

@RestController
public class SampleController {
    
    @GetMapping("/hello/{name}")
    public String hello(@PathVariable("name") Person person){
        return "hello " + person.getName();
    }
}
public class Person {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

그러나 여기서 테스트는 실패한다. 스프링 MVC가 문자열을 Person으로 어떻게 바꿀지 모르기 때문이다. 그걸 알려줄 수 있는 것이 Formatter이다.

public class PersonFormatter implements Formatter<Person> {
    @Override
    public Person parse(String text, Locale locale) throws ParseException {
        Person person = new Person();
        person.setName(text);
        return person;
    }

    @Override
    public String print(Person object, Locale locale) {
        return object.toString();
    }
}

Formatter를 등록하는 방법

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new PersonFormatter());
    }
}

또한 PathVariable 말고 RequestParam도 동작한다.

@RestController
public class SampleController {

    @GetMapping("/hello")
    public String hello(@RequestParam("name") Person person){
        return "hello " + person.getName();
    }
@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void hello() throws Exception{
        this.mockMvc.perform(get("/hello")
                .param("name", "spring"))
                .andDo(print())
                .andExpect(content().string("hello spring"));
    }
}

그러나 스프링 부트에서는 Formatter가 빈으로 등록이 되어 있으면 FormatterRegistry에 등록을 하지 않아도 된다.

@Component
public class PersonFormatter implements Formatter<Person> {
    @Override
    public Person parse(String text, Locale locale) throws ParseException {
        Person person = new Person();
        person.setName(text);
        return person;
    }

    @Override
    public String print(Person object, Locale locale) {
        return object.toString();
    }
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
}

그런데 테스트는 깨진다. 테스트 코드의 @WebMvcTest 어노테이션은 웹과 관련된 빈만 등록해주기 때문이다.(@Component) 따라서 @SpringBootTest 어노테이션으로 바꾸면 모든 빈을 등록해준다. 하지만 이렇게 되면 MockMvc를 자동으로 빈으로 등록해주지 않기 때문에, @AutoConfigureMockMvc 어노테이션을 추가해줘야 한다.

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SampleControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void hello() throws Exception{
        this.mockMvc.perform(get("/hello")
                .param("name", "spring"))
                .andDo(print())
                .andExpect(content().string("hello spring"));
    }
}

포매터 추가하는 방법 1

  • WebMvcConfigurer의 addFormatters(FormatterRegistry) 메소드 정의

포매터 추가하는 방법 2 (스프링 부트 사용시에만 가능 함)

  • 해당 포매터를 빈으로 등록

참고

profile
이것저것 관심많은 개발자.

0개의 댓글