SpringBoot(十六):SpringBoot2.1.1集成fastjson,並使用fastjson替代默認的MappingJackson


springboot2.1.1默認采用的json converter是MappingJackson,通過調試springboot項目中代碼可以確定這點。在springboot項目中定義WebMvcConfig.java

@Configuration
@Import({WebMvcAutoConfiguration.class})
@ComponentScan(
        value = "com.dx.test.web",
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)
        })
public class WebMvcConfig implements WebMvcConfigurer {
    /**
     * 使用 fastjson 代替 jackson
     *
     * @param converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        List<HttpMessageConverter<?>> myConverters = converters;
    }
}

斷電設置在"List<HttpMessageConverter<?>> myConverters = converters;"這行代碼處,然后調試進入該出斷電,查看converters集合下元素:

 

 從上表調試截圖,可以發現springboot2.1.1默認采用的json converter是MappingJackson。

新建SpringBoot項目,並引入fastjson:

pom.xml配置如下:

 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <!-- springboot web組件依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.56</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

SpringBoot入口類:

package com.dx.test.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Hello world!
 */
@SpringBootApplication(scanBasePackages = {"com.dx.test"})
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

使用fastjson作為springboot2.x的json converter的兩種實現方法:

  1. 實現WebMvcConfigurer接口的void configureMessageConverters(List<HttpMessageConverter<?>> converters)方法;
  2. 在WebMvcConfigurer接口實現類內定義bean(HttpMessageConverters)

為什么要使用fastjson替換jackson呢?

1)fastjson快;

2)國產,支持國產。

實現WebMvcConfigurer接口來使用fastjson:

實現代碼如下:

/**
 * WebMvcConfigurerAdapter 這個類在SpringBoot2.0已過時,官方推薦直接實現 WebMvcConfigurer 這個接口
 */
@Configuration
@Import({WebMvcAutoConfiguration.class})
@ComponentScan(
        value = "com.dx.test.web",
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)
        })
public class WebMvcConfig implements WebMvcConfigurer {
    /**
     * 使用 fastjson 代替 jackson
     *
     * @param converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        /*
         先把JackSon的消息轉換器刪除.
         備注:(1)源碼分析可知,返回json的過程為:
                 Controller調用結束后返回一個數據對象,for循環遍歷conventers,找到支持application/json的HttpMessageConverter,然后將返回的數據序列化成json。
                 具體參考org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法
             (2)由於是list結構,我們添加的fastjson在最后。因此必須要將jackson的轉換器刪除,不然會先匹配上jackson,導致沒使用 fastjson
        */
        for (int i = converters.size() - 1; i >= 0; i--) {
            if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
                converters.remove(i);
            }
        }

        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
        //自定義fastjson配置
        FastJsonConfig config = new FastJsonConfig();
        config.setSerializerFeatures(
                SerializerFeature.WriteMapNullValue,        // 是否輸出值為null的字段,默認為false,我們將它打開
                SerializerFeature.WriteNullListAsEmpty,     // 將Collection類型字段的字段空值輸出為[]
                SerializerFeature.WriteNullStringAsEmpty,   // 將字符串類型字段的空值輸出為空字符串
                SerializerFeature.WriteNullNumberAsZero,    // 將數值類型字段的空值輸出為0
                SerializerFeature.WriteDateUseDateFormat,
                SerializerFeature.DisableCircularReferenceDetect    // 禁用循環引用
        );
        fastJsonHttpMessageConverter.setFastJsonConfig(config);

        // 添加支持的MediaTypes;不添加時默認為*/*,也就是默認支持全部
        // 但是MappingJackson2HttpMessageConverter里面支持的MediaTypes為application/json
        // 參考它的做法, fastjson也只添加application/json的MediaType
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
        converters.add(fastJsonHttpMessageConverter);
    }
}

實現思路,先把jackson從converters中移除掉,然后加入fastjson converter。

注意:

1)在該fastjson converter注入時,設置了fastjson配置信息:FastJsonConfig.setSerializerFeatures(循環依賴,是否輸出null的字段等),這些設置將會影響Restful Api輸出信息。

2)但是這個設置並不會影響系統JSON.toJSONString(List<Article>)的配置信息,如果需要控制序列化配置,需要這么使用:

// 序列化為json
String content = JSON.toJSONString(orderByItems, SerializerFeature.WriteMapNullValue);

在WebMvcConfigurer接口實現類內定義bean(HttpMessageConverters)來使用fastjson:

實現代碼如下:

/**
 * WebMvcConfigurerAdapter 這個類在SpringBoot2.0已過時,官方推薦直接實現 WebMvcConfigurer 這個接口
 */
@Configuration
@Import({WebMvcAutoConfiguration.class})
@ComponentScan(
        value = "com.dx.test.web",
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)
        })
public class WebMvcConfig implements WebMvcConfigurer {
    /**
     * +支持fastjson的HttpMessageConverter
     *
     * @return HttpMessageConverters
     */
    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters() {
        AbstractHttpMessageConverter abstractHttpMessageConverter = null;
        //1.需要定義一個convert轉換消息的對象;
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();

        //2:添加fastJson的配置信息;
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat,
                SerializerFeature.DisableCircularReferenceDetect);
        fastJsonConfig.setCharset(Charset.forName("utf-8"));

        //3處理中文亂碼問題
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);

        //4.在convert中添加配置信息.
        fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
        fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);

        HttpMessageConverter<?> converter = fastJsonHttpMessageConverter;

        return new HttpMessageConverters(converter);
    }
}

該方式會自動覆蓋(替換jackson converter)。

針對json輸出字段處理:格式化日期&控制字段是否輸出:

1)日期格式化輸出設置:只需要在實體的屬性上添加注解@JSONField(format = "yyyy-MM-dd")

public class MyVo {
    
    ...

    @JSONField(format = "yyyy-MM-dd")
    @ApiModelProperty(value = "最新StartTime,不存在時,返回null")
    private Date lastStartTimePlus1Day;// 最新startTime

    /**
     * @return the lastStartTimePlus1Day
     */
    public Date getLastStartTimePlus1Day() {
        return lastStartTimePlus1Day;
    }

    /**
     * @param lastStartTimePlus1Day the lastStartTimePlus1Day to set
     */
    public void setLastStartTimePlus1Day(Date lastStartTimePlus1Day) {
        this.lastStartTimePlus1Day = lastStartTimePlus1Day;
    }
}

2)控制字段是否輸出,添加注解

public class MyVo{
        ...
    @JSONField(serialize = true)
    @ApiModelProperty("權重排序:僅排序使用,序列化不輸出")
    private Double weight;
    /**
     * @return the weight
     */
    public Double getWeight() {
        return weight;
    }

    /**
     * @param weight the weight to set
     */
    public void setWeight(Double weight) {
        this.weight = weight;
    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM