[SPRING MVC] Formatter
1014 스프링mvc formatter
Formatter ?
- 문자열을 객체로 변환시키거나 객체를 문자열로 변환해주는 일을 한다.
Person.java
@Getter
@Setter
public class Person {
private String name;
}
SampleController.java
@RestController
public class SampleController {
@GetMapping("/hello/{name}")
public String helloPathVariable(@PathVariable("name") Person person) {
return "hello this is pathVar. "+person.getName();
}
@GetMapping("/hello")
public String helloRequestParam(@RequestParam("name") Person person) {
return "hello this is reqParam. "+person.getName();
}
}
위의 예제는 Formatter 설정이 없으면 에러난다. name
을 적절한 객체로 변환시켜주지 못했기 때문이다.
샘플코드를 제대로 동작시키기위해서 Formatter 설정을 해보자.
PersonFormatter.java
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();
}
}
Formatter
를 구현해야한다. 제네릭타입은 문자열을 객체로, 객체를 문자열로 변환시켜 줄 객체타입이 들어가야된다.
public Person parse(String s, Locale locale) throws ParseException { ... }
은 문자열을 객체로 변환시켜 출력할 때 사용되고, public String print(Person person, Locale locale) {...}
은 객체를 문자열로 변환시켜줄 때 필요하다.
Formatter
작성이 끝났으면, 스프링MVC에 달아줘야한다. 어떻게? WebMvcConfigure
를 구현함으로써. 다음 예제를 보자.
WebConfig.java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new PersonFormatter());
}
}
스프링레거시를 쓸 때는 이와 같이
public void addFormatters(FormatterRegistry registry) { ... }
메소드를 이용하면된다.스프링 부트를 쓸 때는 이런 설정없이
Formatter
를 빈으로 등록시켜주면 된다.PersonFormatter.java
@Component 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(); } }
테스트코드 작성
SampleControllerTest.java
@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception {
mockMvc.perform(get("/hello/eunmo"))
.andExpect(status().isOk())
.andDo(print())
.andExpect(content().string("hello this is pathVar. eunmo"));
}
@Test
public void hello2() throws Exception {
mockMvc.perform(get("/hello?name=eunmo"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello this is reqParam. eunmo"));
}
@Test
public void hello3() throws Exception {
mockMvc.perform(get("/hello")
.param("name","eunmo"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello this is reqParam. eunmo"));
}
}
이 테스트코드가 성공하기 위해선 앞서말한 addFormatter
메서드를 이용해야한다. 왜냐하면 @WebMvcTest
는 웹과 관련된 빈들만 만들어주기 때문이다.
Formatter
자체를 @Component
를 사용해 빈으로 등록시켜줬다면 @Controller
와 같은 웹과 관련된 빈이 아니므로 테스트가 깨진다. 다음과 같은 방법을 사용하자.
명시적으로 빈으로 등록한 후 테스트를 한다.
@WebMvcTest
어노테이션 대신@SpringBootTest
를 사용해 모든 빈을 등록시켜서 테스트를 한다. (이 때는MockMvc
를 주입받을 수 없으므로@AutoConfigureMockMvc
또한 붙여줘야한다.)
SampleControllerTest.java
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception {
mockMvc.perform(get("/hello/eunmo"))
.andExpect(status().isOk())
.andDo(print())
.andExpect(content().string("hello this is pathVar. eunmo"));
}
@Test
public void hello2() throws Exception {
mockMvc.perform(get("/hello?name=eunmo"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello this is reqParam. eunmo"));
}
@Test
public void hello3() throws Exception {
mockMvc.perform(get("/hello")
.param("name","eunmo"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("hello this is reqParam. eunmo"));
}
}