스프링 MVC 설정(9) : WebMvcConfigure - HTTP 메시지 컨버터 + JSON, XML

de_sj_awa·2021년 6월 27일
0

12. HTTP 메시지 컨버터

HTTP 메시지 컨버터

  • 요청 본문에서 메시지를 읽어들이거나(@RequestBody), 응답 본문에 메시지를 작성할 때(@ResponseBody) 사용한다.
@RestController
public class SampleController {

    @GetMapping("/message")
    public @ResponseBody String message(@RequestBody String body){
        return body;
    }
}

테스트 작성

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

    @Autowired
    MockMvc mockMvc;

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

기본 HTTP 메시지 컨버터

  • 바이트 배열 컨버터
  • 문자열 컨버터
  • Resource 컨버터
  • Form 컨버터 (폼 데이터 to/from MultiValueMap<String, String>)

여기서부터는 classpath에 있는 경우만 등록된다.

  • (JAXB2 컨버터)
  • (Jackson2 컨버터)
  • (Jackson 컨버터)
  • (Gson 컨버터)
  • (Atom 컨버터)
  • (RSS 컨버터)
  • ...

어떤 메시지 컨버터를 쓸지는 요청 헤더에 Content-Type, accpet을 보고 결정한다.

또 WebMvcConfigure에 configureConverters라는 메소드를 통해 메시지 컨버터를 추가할 수도 있지만 이를 사용해 메시지 컨버터를 추가하면 기본 컨버터는 사용할 수 없다. 따라서 추가만 하고 싶은 경우는 extendMessageConverts라는 메소드를 사용하면 된다.

설정 방법

  • 기본으로 등록해주는 컨버터에 새로운 컨버터 추가하기: extendMessageConverters
  • 기본으로 등록해주는 컨버터는 다 무시하고 새로 컨버터 설정하기 : configureMessageConverters
  • 의존성 추가로 컨버터 등록하기 (추천)
    - 메이븐 또는 그래들 설정에 의존성을 추가하면 그에 따른 컨버터가 자동으로 등록 된다.
    • WebMvcConfigurationSupport
      - (이 기능 자체는 스프링 프레임워크의 기능임, 스프링 부트 아님.)

13. HTTP 메시지 컨버터 JSON

스프링 부트를 사용하지 않는 경우(WebMvcConfigurationSupport)

  • 사용하고 싶은 JSON 라이브러리를 의존성으로 추가
  • GSON
  • JacksonJSON
  • JacksonJSON 2

스프링 부트를 사용하는 경우

  • 기본적으로 JacksonJSON 2가 의존성에 들어있다.
  • 즉, JSON용 HTTP 메시지 컨버터가 기본으로 등록되어 있다.

도메인 클래스

@Entity
public class Person {

    @Id @GeneratedValue
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

컨트롤러 클래스

@RestController
public class SampleController {

    @GetMapping("/jsonMessage")
    public Person jsonMessage(@RequestBody Person person){
        return person;
    }
}

테스트 코드

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

    @Autowired
    MockMvc mockMvc;

    @Autowired
    PersonRepository personRepository;

    @Autowired
    ObjectMapper objectMapper;

    @Test
    public void jsonMessage() throws Exception {
        Person person = new Person();
        person.setId(2019l);
        person.setName("spring");

        String jsonString = objectMapper.writeValueAsString(person);

        this.mockMvc.perform(get("/jsonMessage")
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(jsonString)
                .accept(MediaType.APPLICATION_JSON_UTF8))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").value(2019))
                .andExpect(jsonPath("$.name").value("spring"));
    }
}

json 응답의 본문을 확인할 때는 JSON path를 사용할 수 있다.

또는 postman이라는 클라이언트를 통해 서버를 띄워서 테스트할 수도 있다.

14. HTTP 메시지 컨버터 XML

OXM(Object-XML Mapper) 라이브러리 중에 스프링이 지원하는 의존성 추가

  • JacksonXML
  • JAXB

스프링 부트를 사용하는 경우

  • 기본으로 XML 의존성 추가해주지 않음.
  • WebMvcConfigurer에 Bean으로 Jaxb2Marshaller 메시지 컨버터 등록
  1. pom.xml에 JAXB 의존성 추가
<dependency> 
	<groupId>javax.xml.bind</groupId> 
	<artifactId>jaxb-api</artifactId> 
</dependency> 
<dependency> 
	<groupId>org.glassfish.jaxb</groupId> 
	<artifactId>jaxb-runtime</artifactId> 
</dependency> 
<dependency> 
	<groupId>org.springframework</groupId> 
	<artifactId>spring-oxm</artifactId> 
	<version>${spring-framework.version}</version> 
</dependency>
  1. WebMvcConfigurer에 Bean으로 Jaxb2Marshaller 메시지 컨버터 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public Jaxb2Marshaller jaxb2Marshaller(){
        Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
        jaxb2Marshaller.setPackagesToScan(Person.class.getPackageName());
        // Person.class가 있는 패키지 이름을 scan해서 
        // @XmlRootElement 애노테이션이 있는지 확인
        return jaxb2Marshaller;
    }
}
  1. 도메인 클래스에 @XmlRootElement 애노테이션 추가
@XmlRootElement
@Entity
public class Person {

    @Id @GeneratedValue
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  1. 테스트 코드
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SampleControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    PersonRepository personRepository;

    @Autowired
    Marshaller marshaller;

    @Test
    public void xmlMessage() throws Exception {
        Person person = new Person();
        person.setId(2019l);
        person.setName("spring");

        StringWriter stringWriter = new StringWriter();
        Result result = new StreamResult(stringWriter);
        marshaller.marshal(person, result);
        String xmlString = stringWriter.toString();

        this.mockMvc.perform(get("/jsonMessage")
                .contentType(MediaType.APPLICATION_XML)
                .content(xmlString)
                .accept(MediaType.APPLICATION_XML))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(xpath("person/name").string("seonju"))
                .andExpect(xpath("person/id").string("2019"));
    }
}

xml 응답의 본문을 확인할 때는 Xpath를 사용할 수 있다.

역시 postman이라는 클라이언트를 통해 서버를 띄워서 테스트할 수도 있다.

참고

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

0개의 댓글