springboot2 global configuration formatted date (including front-end incoming and back-end return)

Backend returns configuration

1. Jackson version

1.1 Add the following configuration

Note that @AutoConfigureBefore(JacksonAutoConfiguration.class)the purpose is to build the ObjectMapper in advance, so that when JacksonAutoConfiguration is initialized, the custom ObjectMapper is used, and the formatting parameters we configured can take effect.

package com.czt.szcz.quota.accounting.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.TimeZone;

@Configuration
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfig {
    
    
	/**
     * 年-月-日
     */
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    /**
     * 年-月-日 时:分
     */
    public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
    /**
     * 年-月-日 时:分:秒
     */
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    /**
     * 年-月-日 时:分:秒:毫秒
     */
    public static final String YYYY_MM_DD_HH_MM_SS_S = "yyyy-MM-dd HH:mm:ss.S";

    /**
     * 时:分
     */
    public static final String HH_MM = "HH:mm";
    /**
     * 时:分:秒
     */
    public static final String HH_MM_SS = "HH:mm:ss";
    /**
     * 时:分:秒:毫秒
     */
    public static final String HH_MM_SS_S = "HH:mm:ss:S";
    
    @Bean
    public ObjectMapper objectMapper() {
    
    
        ObjectMapper objectMapper = new ObjectMapper();
        // 生成JSON时,将所有Long转换成String
//        SimpleModule simpleModule = new SimpleModule();
//        simpleModule.addSerializer(Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
//        simpleModule.addSerializer(Long.TYPE, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
//        objectMapper.registerModule(simpleModule);

        // 忽略json字符串中不识别的属性
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 忽略无法转换的对象
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // PrettyPrinter 格式化输出
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
        // NULL不参与序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 指定地区
        objectMapper.setLocale(Locale.CHINA);

        // 指定时区
        objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));

        // 日期类型字符串处理
        objectMapper.setDateFormat(new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS));

        // java8日期日期处理
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS)));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(YYYY_MM_DD)));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(HH_MM_SS)));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS)));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(YYYY_MM_DD)));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(HH_MM_SS)));
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }
}
1.2 Test results

insert image description here

2. Fastjson version

2.1 Introduce fastjson dependency
<!-- alibaba fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>
2.2 Custom DateTimeSerializer
package org.demo.common.serializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;

import java.io.IOException;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 日期格式化
 */
public class DateTimeSerializer implements ObjectSerializer {
    
    
    public static final DateTimeSerializer instance = new DateTimeSerializer();
    private static final String DATE_PATTERN = "yyyy-MM-dd";
    private static final String TIME_PATTERN = "HH:mm:ss";
    private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public DateTimeSerializer() {
    
    
    }

    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
    
    
        SerializeWriter out = serializer.out;
        if (object == null) {
    
    
            out.writeNull();
        } else if (object instanceof Timestamp) {
    
    
            Timestamp result = (Timestamp) object;
            out.writeString(new SimpleDateFormat(DATE_TIME_PATTERN).format(result));
        } else if (object instanceof Date) {
    
    
            Date result = (Date) object;
            out.writeString(new SimpleDateFormat(DATE_PATTERN).format(result));
        } else if (object instanceof LocalDate) {
    
    
            LocalDate result = (LocalDate) object;
            out.writeString(result.format(DateTimeFormatter.ofPattern(DATE_PATTERN)));
        } else if (object instanceof LocalTime) {
    
    
            LocalTime result = (LocalTime) object;
            out.writeString(result.format(DateTimeFormatter.ofPattern(TIME_PATTERN)));
        } else if (object instanceof LocalDateTime) {
    
    
            LocalDateTime result = (LocalDateTime) object;
            out.writeString(result.format(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN)));
        }
    }
}
2.3 Custom fastjson configuration
package org.demo.config;

import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.demo.common.serializer.DateTimeSerializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * fastjson转换结果
 *
 * @author huangqinhua
 * @version 1.0.0
 * @date 2021/8/31 18:55
 */
@Configuration
public class FastJsonHttpMessageConverterConfig implements WebMvcConfigurer {
    
    
    /**
     * Long及Date类型转换
     *
     * @param converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    
    
        // 1.需要定义一个convert转换消息的对象
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();

        // 2.添加fastJson的配置信息,比如:是否要格式化返回的json数据
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
            // 保留 Map 空的字段
            SerializerFeature.WriteMapNullValue,
            // 将 String 类型的 null 转成""
            SerializerFeature.WriteNullStringAsEmpty,
            // 将 Number 类型的 null 转成 0
            SerializerFeature.WriteNullNumberAsZero,
            // 将 List 类型的 null 转成 []
            SerializerFeature.WriteNullListAsEmpty,
            // 将 Boolean 类型的 null 转成 false
            SerializerFeature.WriteNullBooleanAsFalse,
            // 避免循环引用
            SerializerFeature.DisableCircularReferenceDetect,
            SerializerFeature.PrettyFormat,
            SerializerFeature.WriteDateUseDateFormat);

        // 解决返回前端的Long精度丢失问题
        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
        serializeConfig.put(Long.class , ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE , ToStringSerializer.instance);

        // 日期格式化返回,解决LocalTime秒为00时不显示的问题
        serializeConfig.put(Date.class, DateTimeSerializer.instance);
        serializeConfig.put(Timestamp.class , DateTimeSerializer.instance);
        serializeConfig.put(LocalDate.class , DateTimeSerializer.instance);
        serializeConfig.put(LocalTime.class , DateTimeSerializer.instance);
        serializeConfig.put(LocalDateTime.class , DateTimeSerializer.instance);

        // 添加配置
        fastJsonConfig.setSerializeConfig(serializeConfig);

        // 3.处理中文乱码问题
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.valueOf("application/json;charset=UTF-8"));

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

        // 5.将convert添加到converters当中
        converters.add(0, fastJsonHttpMessageConverter);
    }

    /**
     * 因为使用了统一结果转换,所以要删除这个解析器,不然返回值为String时会报错
     *
     * 删除springboot默认的StringHttpMessageConverter解析器
     *
     * @param converters
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    
    
        converters.removeIf(x -> x instanceof StringHttpMessageConverter);
    }
}
2.4 Testing

The configuration of fastjson is to format the Date into yyyy-MM-dd, you can change the configuration yourself
insert image description here

Front-end incoming configuration

Just add the following configuration

import cn.hutool.core.date.DateUtil;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;

import java.beans.PropertyEditorSupport;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 全局空字符串和日期处理
 */
@ControllerAdvice
public class GlobalControllerAdvice {
    
    
    /**
     * 把空字符串转为null,前端传""过来就能转为null
     *
     * @param binder
     */
    @InitBinder
    public void emptyStringToNull(WebDataBinder binder) {
    
    
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }

    /**
     * 统一日期转换(用于非json的日期字符串转换)
     *
     * json的由FastJsonHttpMessageConverterConfig处理
     *
     * @param binder
     */
    @InitBinder
    public void dateBinder(WebDataBinder binder) {
    
    
        // Date 类型转换
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
    
    
            @Override
            public void setAsText(String text) {
    
    
                setValue(DateUtil.parseDate(text));
            }
        });

        // LocalDateTime
        binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() {
    
    
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
    
    
                setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
        });

        // LocalDate
        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
    
    
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
    
    
                setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
        });

        // LocalTime
        binder.registerCustomEditor(LocalTime.class, new PropertyEditorSupport() {
    
    
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
    
    
                setValue(LocalTime.parse(text, DateTimeFormatter.ofPattern("HH:mm:ss")));
            }
        });
    }
}
test

An error will be reported when no configuration is added
insert image description here

After adding the configuration, the String date is normally converted to the corresponding date type
insert image description here

Guess you like

Origin blog.csdn.net/q283614346/article/details/130399636