如何在 spring boot 2 中通过内容协商建立自定义 xml 序列化
How to establish a custom xml serialization with content negotiation in spring boot 2
我正在重构 REST-API 并想向其添加内容协商。到目前为止有效。
现在我尝试为所有请求添加自定义 xml 序列化程序。但它没有或没有被正确调用。
问题是,我无权访问 需要在导入时序列化的 Class (Catalog.class
)。因此我需要一个外部解决方案。注释 class 不起作用。
我尝试使用 ObjectMapper
。但这并没有直接帮助我。目标是让 spring 引导在发送响应时自动使用我的 xml 解析器。
我已经尝试过以下方法:
创建了一个 XmlMapper
@Bean
public XmlMapper getXmlMapper() {
XmlMapper mapper = new XmlMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Catalog.class, new CatalogV2Resource.Serializer());
mapper.registerModule(module);
mapper.findAndRegisterModules();
mapper.setSerializerProvider(new DefaultSerializerProvider.Impl());
return mapper;
}
尝试将其添加为 RestTemplate 的默认设置
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2XmlHttpMessageConverter) {
MappingJackson2XmlHttpMessageConverter jsonConverter = (MappingJackson2XmlHttpMessageConverter) converter;
jsonConverter.setObjectMapper(xmlMapper);
}
}
return restTemplate;
}
这是我的序列化程序
public static class Serializer extends StdSerializer<com.allianz.kb.Catalog> {
@Override
public void serialize(Catalog catalog, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (jsonGenerator instanceof ToXmlGenerator) {
jsonGenerator.writeRaw(new KbParser().toXML(catalog)); //use my own parser
}
}
}
以及控制器的简化版本。
@PostMapping(value = "/newcatalog", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Catalog> doPostXML(@RequestParam String name) {
//removed the stuff here for simplicity reasons
Catalog catalog = nc.getNewCatalog();
return ResponseEntity.ok(catalog);
}
我希望,只要收到带有 'Accept application/xml' 的请求,我的解析器就会自动调用。因此,我的 XML-parser 被调用用于 XML 请求,而标准 JSON 解析器被调用用于 JSON 请求。
非常感谢对此的任何帮助。
非常感谢!
对于自动 XML 序列化和反序列化,您需要注册类型为 MappingJackson2XmlHttpMessageConverter
的 bean,如下所示 -
@Bean("mappingJackson2XmlHttpMessageConverter")
public MappingJackson2XmlHttpMessageConverter mappingJackson2XmlHttpMessageConverter()
{
return new MappingJackson2XmlHttpMessageConverter(new XmlMapper());
}
我最终使用了以下 class。好像我错过了 @EnableWebMvc
注释以及 implements WebMvcConfigurer
@Configuration
@EnableWebMvc
public class CustomSerializerConfiguration implements WebMvcConfigurer {
@Bean
public Module catalogSerializer() {
SimpleModule module = new SimpleModule();
module.addSerializer(com.allianz.kb.Catalog.class, new CustomCatalogSerializer(Catalog.class));
return module;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
// more customization available
// builder.serializationInclusion(JsonInclude.Include.NON_NULL);
// builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
// builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
builder.modulesToInstall(catalogSerializer());
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
}
}
我正在重构 REST-API 并想向其添加内容协商。到目前为止有效。 现在我尝试为所有请求添加自定义 xml 序列化程序。但它没有或没有被正确调用。
问题是,我无权访问 需要在导入时序列化的 Class (Catalog.class
)。因此我需要一个外部解决方案。注释 class 不起作用。
我尝试使用 ObjectMapper
。但这并没有直接帮助我。目标是让 spring 引导在发送响应时自动使用我的 xml 解析器。
我已经尝试过以下方法:
创建了一个 XmlMapper
@Bean
public XmlMapper getXmlMapper() {
XmlMapper mapper = new XmlMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Catalog.class, new CatalogV2Resource.Serializer());
mapper.registerModule(module);
mapper.findAndRegisterModules();
mapper.setSerializerProvider(new DefaultSerializerProvider.Impl());
return mapper;
}
尝试将其添加为 RestTemplate 的默认设置
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2XmlHttpMessageConverter) {
MappingJackson2XmlHttpMessageConverter jsonConverter = (MappingJackson2XmlHttpMessageConverter) converter;
jsonConverter.setObjectMapper(xmlMapper);
}
}
return restTemplate;
}
这是我的序列化程序
public static class Serializer extends StdSerializer<com.allianz.kb.Catalog> {
@Override
public void serialize(Catalog catalog, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (jsonGenerator instanceof ToXmlGenerator) {
jsonGenerator.writeRaw(new KbParser().toXML(catalog)); //use my own parser
}
}
}
以及控制器的简化版本。
@PostMapping(value = "/newcatalog", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Catalog> doPostXML(@RequestParam String name) {
//removed the stuff here for simplicity reasons
Catalog catalog = nc.getNewCatalog();
return ResponseEntity.ok(catalog);
}
我希望,只要收到带有 'Accept application/xml' 的请求,我的解析器就会自动调用。因此,我的 XML-parser 被调用用于 XML 请求,而标准 JSON 解析器被调用用于 JSON 请求。
非常感谢对此的任何帮助。 非常感谢!
对于自动 XML 序列化和反序列化,您需要注册类型为 MappingJackson2XmlHttpMessageConverter
的 bean,如下所示 -
@Bean("mappingJackson2XmlHttpMessageConverter")
public MappingJackson2XmlHttpMessageConverter mappingJackson2XmlHttpMessageConverter()
{
return new MappingJackson2XmlHttpMessageConverter(new XmlMapper());
}
我最终使用了以下 class。好像我错过了 @EnableWebMvc
注释以及 implements WebMvcConfigurer
@Configuration
@EnableWebMvc
public class CustomSerializerConfiguration implements WebMvcConfigurer {
@Bean
public Module catalogSerializer() {
SimpleModule module = new SimpleModule();
module.addSerializer(com.allianz.kb.Catalog.class, new CustomCatalogSerializer(Catalog.class));
return module;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
// more customization available
// builder.serializationInclusion(JsonInclude.Include.NON_NULL);
// builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
// builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
builder.modulesToInstall(catalogSerializer());
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
}
}