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;
    }

}

posted @ 2023-08-10 08:05  unknown-n2  阅读(94)  评论(0编辑  收藏  举报