HTTP Message Converterは、Bodyに送信されたJSON/XMLデータの処理に用いられる
この文章の目的は?
マスターに渡されたJSON/XMLデータをオブジェクトに変換する方法
HTTP Message Converter?
リクエスト本文からメッセージを読み込むか、レスポンス本文にメッセージを作成します.すなわち、@RequestBody, @ResponseBody
の音声を使用する場合、要求/応答を処理する変換器である.
この設定は、依存性に応じて条件付きで登録され、WebMvcConfigurationSupportクラスのコードで見つけることができます.public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
// (생략...)
static {
ClassLoader classLoader = WebMvcConfigurationSupport.class.getClassLoader();
romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
kotlinSerializationJsonPresent = ClassUtils.isPresent("kotlinx.serialization.json.Json", classLoader);
}
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new ResourceRegionHttpMessageConverter());
if (!shouldIgnoreXml) {
try {
messageConverters.add(new SourceHttpMessageConverter());
} catch (Throwable var3) {
}
}
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
messageConverters.add(new AtomFeedHttpMessageConverter());
messageConverters.add(new RssChannelHttpMessageConverter());
}
Jackson2ObjectMapperBuilder builder;
if (!shouldIgnoreXml) {
if (jackson2XmlPresent) {
builder = Jackson2ObjectMapperBuilder.xml();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
} else if (jaxb2Present) {
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
}
if (kotlinSerializationJsonPresent) {
messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
}
if (jackson2Present) {
builder = Jackson2ObjectMapperBuilder.json();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
} else if (gsonPresent) {
messageConverters.add(new GsonHttpMessageConverter());
} else if (jsonbPresent) {
messageConverters.add(new JsonbHttpMessageConverter());
}
if (jackson2SmilePresent) {
builder = Jackson2ObjectMapperBuilder.smile();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
}
if (jackson2CborPresent) {
builder = Jackson2ObjectMapperBuilder.cbor();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
}
}
// (생략...)
}
HTTP Message Converterが理解しなければならないのは、Spring Bootの機能ではなく、Springフレームワーク自体の機能です.Spring Bootにおいてのみ,基本的にJacksonJSON 2は依存性を持つ.(スプリングガイドを使用しない場合は、JSONライブラリを依存項目に直接追加する必要があります.)
基本的に多くのHTTPメッセージ変換器が提供されており、追加作業はほとんどありません.😆 ただし、新しいConverterを追加する場合は、WebConfiguratorインタフェースを使用して登録するか、依存性を簡単に追加するだけで登録できます.△講座では、白奇仙が依存性を加えた登録方法を推薦した.
WebConfiguratorインタフェースに登録する場合、2つの方法を追加できます.configureMessageConverters()
メソッドは、デフォルト登録されているすべてのConverterを無視するため、extendMessageConverters()
メソッドを使用してデフォルト登録されているConverterに追加登録するとより安全です.@Configuration
public class WebConfig implements WebMvcConfigurer {
// @Override
// public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// // 추가할 경우에는 기본적으로 제공하는 메시지 컨버터를 사용할 수 없음
// }
// @Override
// public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// // 기본적으로 제공하는 메시지 컨버터에 추가
// }
}
@RestController
public class SimpleController {
@GetMapping("/message")
public String messageString(@RequestBody String body) {
return "message " + body;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SimpleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void messageString() throws Exception {
this.mockMvc.perform(get("/message").content("body"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("message body"));
}
}
JSON
Spring Bootでは、基本的にJSON依存性が存在するため、依存性を追加せずに確認することができる.@RestController
public class SimpleController {
@GetMapping("/jsonmessage")
public Person jsonmessage(@RequestBody Person person) {
return person;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SimpleControllerTest {
@Autowired
MockMvc mockMvc;
@Autowired
ObjectMapper objectMapper;
@Test
public void jsonmessage() throws Exception {
Person person = new Person();
person.setId(10L);
person.setName("kevin");
// 객체를 JSON으로 변환
String jsonString = objectMapper.writeValueAsString(person);
this.mockMvc.perform(get("/jsonmessage")
.contentType(MediaType.APPLICATION_JSON) // JSON 요청을 보냄
.accept(MediaType.APPLICATION_JSON) // JSON 응답을 기대
.content(jsonString))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(10L))
.andExpect(jsonPath("$.name").value("kevin"));
}
}
テストコードで使用されるJSON Path構文は、次のリンクを参照して記述できます.
リクエスト本文からメッセージを読み込むか、レスポンス本文にメッセージを作成します.すなわち、
@RequestBody, @ResponseBody
の音声を使用する場合、要求/応答を処理する変換器である.この設定は、依存性に応じて条件付きで登録され、WebMvcConfigurationSupportクラスのコードで見つけることができます.
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
// (생략...)
static {
ClassLoader classLoader = WebMvcConfigurationSupport.class.getClassLoader();
romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
kotlinSerializationJsonPresent = ClassUtils.isPresent("kotlinx.serialization.json.Json", classLoader);
}
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new ResourceRegionHttpMessageConverter());
if (!shouldIgnoreXml) {
try {
messageConverters.add(new SourceHttpMessageConverter());
} catch (Throwable var3) {
}
}
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
messageConverters.add(new AtomFeedHttpMessageConverter());
messageConverters.add(new RssChannelHttpMessageConverter());
}
Jackson2ObjectMapperBuilder builder;
if (!shouldIgnoreXml) {
if (jackson2XmlPresent) {
builder = Jackson2ObjectMapperBuilder.xml();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
} else if (jaxb2Present) {
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
}
if (kotlinSerializationJsonPresent) {
messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
}
if (jackson2Present) {
builder = Jackson2ObjectMapperBuilder.json();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
} else if (gsonPresent) {
messageConverters.add(new GsonHttpMessageConverter());
} else if (jsonbPresent) {
messageConverters.add(new JsonbHttpMessageConverter());
}
if (jackson2SmilePresent) {
builder = Jackson2ObjectMapperBuilder.smile();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
}
if (jackson2CborPresent) {
builder = Jackson2ObjectMapperBuilder.cbor();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
}
}
// (생략...)
}
HTTP Message Converterが理解しなければならないのは、Spring Bootの機能ではなく、Springフレームワーク自体の機能です.Spring Bootにおいてのみ,基本的にJacksonJSON 2は依存性を持つ.(スプリングガイドを使用しない場合は、JSONライブラリを依存項目に直接追加する必要があります.)基本的に多くのHTTPメッセージ変換器が提供されており、追加作業はほとんどありません.😆 ただし、新しいConverterを追加する場合は、WebConfiguratorインタフェースを使用して登録するか、依存性を簡単に追加するだけで登録できます.△講座では、白奇仙が依存性を加えた登録方法を推薦した.
WebConfiguratorインタフェースに登録する場合、2つの方法を追加できます.
configureMessageConverters()
メソッドは、デフォルト登録されているすべてのConverterを無視するため、extendMessageConverters()
メソッドを使用してデフォルト登録されているConverterに追加登録するとより安全です.@Configuration
public class WebConfig implements WebMvcConfigurer {
// @Override
// public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// // 추가할 경우에는 기본적으로 제공하는 메시지 컨버터를 사용할 수 없음
// }
// @Override
// public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// // 기본적으로 제공하는 메시지 컨버터에 추가
// }
}
@RestController
public class SimpleController {
@GetMapping("/message")
public String messageString(@RequestBody String body) {
return "message " + body;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SimpleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void messageString() throws Exception {
this.mockMvc.perform(get("/message").content("body"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("message body"));
}
}
JSON
Spring Bootでは、基本的にJSON依存性が存在するため、依存性を追加せずに確認することができる.
@RestController
public class SimpleController {
@GetMapping("/jsonmessage")
public Person jsonmessage(@RequestBody Person person) {
return person;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SimpleControllerTest {
@Autowired
MockMvc mockMvc;
@Autowired
ObjectMapper objectMapper;
@Test
public void jsonmessage() throws Exception {
Person person = new Person();
person.setId(10L);
person.setName("kevin");
// 객체를 JSON으로 변환
String jsonString = objectMapper.writeValueAsString(person);
this.mockMvc.perform(get("/jsonmessage")
.contentType(MediaType.APPLICATION_JSON) // JSON 요청을 보냄
.accept(MediaType.APPLICATION_JSON) // JSON 응답을 기대
.content(jsonString))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(10L))
.andExpect(jsonPath("$.name").value("kevin"));
}
}
テストコードで使用されるJSON Path構文は、次のリンクを参照して記述できます.XML
JSONと異なりSpring Bootは基本的にXML依存性を追加しないため、単独で追加する必要がある.
OXM(Object-XML Mapper)ライブラリでは、Springがサポートする依存性にはJacksonXMLとJAXBが含まれているため、JAXBを追加できます.
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<!-- xml을 객체로 변환(Marshalling) / 객체를 xml로 변환(UnMarshalling) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring-framework.version}</version>
</dependency>
次に、Marshallerを空に登録し、XMLに変換するクラスに@XmlRootElement
フレーズを追加します.@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setPackagesToScan(Person.class.getPackageName()); // @XmlRootElement 어노테이션 스캔
return jaxb2Marshaller;
}
}
@XmlRootElement
@Getter
@Setter
@Entity
public class Person {
@Id @GeneratedValue
private Long id;
private String name;
}
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SimpleControllerTest {
@Autowired
MockMvc mockMvc;
@Autowired
Marshaller marshaller; // WebConfig에 등록한 빈을 주입 받음
@Test
public void xmlmessage() throws Exception {
Person person = new Person();
person.setId(10L);
person.setName("kevin");
// 객체를 XML로 변환
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) // XML 요청을 보냄
.accept(MediaType.APPLICATION_XML) // XML 응답을 기대
.content(xmlString))
.andDo(print())
.andExpect(status().isOk())
.andExpect(xpath("person/id").string("10"))
.andExpect(xpath("person/name").string("kevin"));
}
}
テストコードで使用されるXML Path構文は、次のリンクを参照して記述できます.本文の参考
Reference
この問題について(HTTP Message Converterは、Bodyに送信されたJSON/XMLデータの処理に用いられる), 我々は、より多くの情報をここで見つけました https://velog.io/@maketheworldwise/Body로-전달된-JSONXML-데이터를-처리하는-HTTP-Message-Converterテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol