Springboot同时注册XMLMappe和ObjectMapperr导致Controller返回xml格式数据
问题
如标题,Springboot同时注册XMLMappe和ObjectMapperr,导致Controller返回xml格式数据。
解决办法
在以下代码中有两点需要注意
- 配置类实现WebMvcConfigruer
- 重写configureMessageConverters方法
package com.example.blog.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* @author unknown
* @since 2023/08/03 00:18
* 继承<P>WebMvcConfigurationSupport</P>和实现<P>WebMvcConfigurer</P>
* WebMvcConfigurationSupport:
* WebMvcConfigurationSupport在整个应用程序中只会生效一个,如果用户已经实现了WebMvcConfigurationSupport
* 则WebMvcConfigurer 的所有实现类将不会生效。而在Spring 中,如果类路径上不存在 WebMvcConfigurationSupport
* 的实例,则将会默认实现WebMvcConfigurerAdapter,DelegatingWebMvcConfiguration 来自定义mvc 配置。
* WebMvcConfigurer:
* 在springboot下自定义的WebMvcConfigurer实现配置类上是不需要添加@EnableWebMvc的,因为springboot已经实例化了
* WebMvcConfigurationSupport,如果添加了该注解,默认的WebMvcConfigurationSupport配置类是不会生效的,
* 也就是以用户定义的为主,一般建议还是不覆盖默认的好。
* 总结:
* WebMvcConfigurationSupport比较适合对框架默认修改比较的多的开发者
* WebMvcConfigurer只需要修改或者重写其中的某些功能
*/
@Configuration
public class JacksonConfig implements WebMvcConfigurer{
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* <P>请求响应消息转换器</P>
* 解决了在同时注册了ObjectMapper和XmlMapper为Bean后,控制层返回数据都是xml类型的问题
* @param converters converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new MappingJackson2HttpMessageConverter(jsonMapper(jackson2ObjectMapperBuilder())));
converters.add(1, new MappingJackson2XmlHttpMessageConverter(xmlMapper(jackson2ObjectMapperBuilder())));
}
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
return new Jackson2ObjectMapperBuilder();
}
/**
* <P>JSON格式的序列化与反序列化</P>
*
* @param builder
* @return ObjectMapper
*/
@Bean
@Qualifier("JSON")
public ObjectMapper jsonMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// JSON序列化JavaBean时,以对象字段为标准,JSON串种多余的字段舍弃,此功能有一个缺点: 不利于查找错误,当JSON串的字段有拼写错误时,JavaBean对应的字段是无法接受到数据的
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 自定义序列化对象
JavaTimeModule javaTimeModule = new JavaTimeModule();
// LocalDateTime 序列化
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
// LocalDateTime 反序列化
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
// 此美化输出的作用体现于<P>每个字段占据一行</P>,类似在其他Json格式化网站一样的功能,方便阅读,生产线上不推荐此功能
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 注册自定义序列化对象
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
/**
* <P>XMl格式的序列化与反序列化</P>
* 问题: 在Springboot中注册了该Bean以后,所有Controller返回的数据格式都是xml
* 解决办法: 重写configureMessageConverters方法,设置优先级
* @param builder
* @return XmlMapper
*/
@Bean
@Primary
@Qualifier("XML")
public XmlMapper xmlMapper(Jackson2ObjectMapperBuilder builder) {
XmlMapper mapper = builder.createXmlMapper(true).build();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
}