最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot JSON全局日期格式轉(zhuǎn)換器實(shí)現(xiàn)方式

 更新時(shí)間:2023年04月17日 11:10:37   作者:fengyehongWorld  
這篇文章主要介紹了SpringBoot JSON全局日期格式轉(zhuǎn)換器,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

需求

前臺(tái)有日期字符串的數(shù)據(jù),提交到后臺(tái)。后臺(tái)實(shí)體類(lèi)使用Date屬性接收。
日期字符串有多種格式,需要用一個(gè)轉(zhuǎn)換器將合法的日期字符串格式轉(zhuǎn)換為Date類(lèi)型。

分析

當(dāng)前臺(tái)的提交數(shù)據(jù)的Content-Typeapplication/json;charset=utf-8,后臺(tái)使用@RequestBody來(lái)接收數(shù)據(jù)的時(shí)候,使用此轉(zhuǎn)換方式。

一. 前期準(zhǔn)備

1.1 日期正則注解

用來(lái)標(biāo)記日期字符串所對(duì)應(yīng)的正則表達(dá)式

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface DatePattern {
	
    String value();
}

1.2 日期格式定數(shù)

指定所有支持的日期格式

public final class DateFormatPart {

	@DatePattern("^\\d{4}$")
	public static final String YYYY = "yyyy";

	@DatePattern("^\\d{4}\\d{2}$")
	public static final String YYYYMM = "yyyyMM";

	@DatePattern("^\\d{4}/\\d{2}$")
	public static final String YYYYMM_SLASH = "yyyy/MM";

	@DatePattern("^\\d{4}\\d{1,2}\\d{1,2}$")
	public static final String YYYYMMDD = "yyyyMMdd";

	@DatePattern("^\\d{4}/\\d{2}/\\d{2}$")
	public static final String YYYYMMDD_SLASH = "yyyy/MM/dd";

	@DatePattern("[0-9]+\\u5e74[0-9]+\\u6708[0-9]+\\u65e5$")
	public static final String YYYYMMDD_JP = "yyyy年MM月dd日";

    @DatePattern("^\\d{4}\\d{1,2}\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}$")
	public static final String YYYYMMDD_HHMMSS = "yyyyMMdd HH:mm:ss";

    @DatePattern("^\\d{4}/\\d{2}/\\d{2} \\d{1,2}:\\d{1,2}:\\d{1,2}$")
	public static final String YYYYMMDD_HHMMSS_SLASH = "yyyy/MM/dd HH:mm:ss";
}

1.3 日期轉(zhuǎn)換工具類(lèi)

  • 從日期格式定數(shù)類(lèi)中獲取所有的屬性值和該屬性上所標(biāo)記的正則注解,通過(guò)反射來(lái)映射為map。
  • 如果有需要增刪的日期格式的話,只需要修改日期格式定數(shù)即可,便于維護(hù)。
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public final class DateUtil {

    // 日期格式 <==> 正則的map,使用LinkedHashMap可以避免按照順序匹配正則表達(dá)式
    private static final Map<String, String> datePatternMap = new LinkedHashMap<>();

    // 日期格式List
    private static final List<String> dateFormatList = new ArrayList<>();

    // 使用靜態(tài)代碼塊,可以保證只初始化一次
    static {

        Class<DateFormatPart> dateFormatClass = DateFormatPart.class;
        // 獲取所有的屬性
        Field[] fields = dateFormatClass.getFields();
        for (Field field : fields) {

            // 獲取屬性上的注解
            DatePattern annotation = field.getAnnotation(DatePattern.class);
            if (ObjectUtils.isEmpty(annotation)) {
                continue;
            }

            //  強(qiáng)制讓屬性可以訪問(wèn)
            ReflectionUtils.makeAccessible(field);

            // 日期格式化字符串
            String dateFormatStr = "";
            try {
                // 獲取當(dāng)前屬性所對(duì)應(yīng)的屬性值
                dateFormatStr = (String)field.get(dateFormatClass);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

            dateFormatList.add(dateFormatStr);

            // 將該屬性的屬性值和屬性上的正則表達(dá)式放到map中
            datePatternMap.put(dateFormatStr, annotation.value());
        }
    }
	
	// 用所有可能支持的格式將日期字符串轉(zhuǎn)換為Date格式
    public static Date formatDateStrToDateAllFormat(String dateStr) {

        if (ObjectUtils.isEmpty(dateStr)) {
            return null;
        }

        try {
            for (Map.Entry<String, String> mapEntry : datePatternMap.entrySet()) {
				
				// 如果當(dāng)前日期字符串不符合當(dāng)前正則的話
                if (!dateStr.matches(mapEntry.getValue())) {
                    continue;
                }

                return DateUtil.formatStringToDate(dateStr, mapEntry.getKey());
            }
        } catch (ParseException e) {
            return null;
        }

        return null;
    }
	
	// 通過(guò)指定的格式將日期字符串轉(zhuǎn)換為Date類(lèi)型
    public static Date formatStringToDate(String dateStr, String format) throws ParseException {

        if (ObjectUtils.isEmpty(dateStr) || !dateFormatList.contains(format)) {
            return null;
        }

        SimpleDateFormat time = new SimpleDateFormat(format);
        return time.parse(dateStr);
    }
}

二. 方式1-繼承DateDeserializer類(lèi),重寫(xiě)_parseDate方法

  • 該方式的要點(diǎn)是通過(guò)繼承DateDeserializer類(lèi),然后重寫(xiě)_parseDate方法實(shí)現(xiàn)轉(zhuǎn)換功能
  • 自定義的GlobalDateDeserializer類(lèi)需要添加到自定義的SimpleModule模塊中,然后將模塊添加到ObjectMapper中,通過(guò)jackson來(lái)實(shí)現(xiàn)轉(zhuǎn)換。
  • 通過(guò)設(shè)置ObjectMapper對(duì)象的setDateFormat方法來(lái)實(shí)現(xiàn)后臺(tái)數(shù)據(jù)返回到前臺(tái)時(shí)的Date轉(zhuǎn)String的默認(rèn)格式。
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.json.PackageVersion;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers.DateDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

@Configuration
public class CustomConfig {

    /*
     * 自定義的全局的日期轉(zhuǎn)換解析類(lèi),需要繼承jackson包中的DateDeserializer
     * 因?yàn)榇祟?lèi)不會(huì)在別的地方使用了,因此直接使用內(nèi)部類(lèi)聚合到自定義的配置文件中
     */
    private static final class GlobalDateDeserializer extends DateDeserializer {

        @Override
        protected Date _parseDate(JsonParser jp, DeserializationContext context) throws IOException {

            return DateUtil.formatDateStrToDateAllFormat(jp.getText());
        }
    }

    @Bean("objectMapper")
    @Primary
    @ConditionalOnMissingBean
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {

        // 創(chuàng)建jackson對(duì)象
        ObjectMapper jackson = builder.createXmlMapper(false).build();

        /*
         * DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
         * 在進(jìn)行序列化或者反序列化的時(shí)候,
         * JSON字符串中有一個(gè)字段,但是我們的對(duì)象沒(méi)有這個(gè)字段的時(shí)候,該怎么處理
         * 設(shè)置為true的時(shí)候,會(huì)拋出異常
         * 設(shè)置為false,忽略異常繼續(xù)處理
         */
        jackson.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 禁用默認(rèn)的「yyyy-MM-dd'T'HH:mm:ss.SSS」UTC類(lèi)型
        jackson.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

         /*
         * 設(shè)置序列化時(shí)的默認(rèn)格式,即后臺(tái)返回?cái)?shù)據(jù)到前臺(tái)的時(shí)候,
         * Date類(lèi)型數(shù)據(jù)需要轉(zhuǎn)換為的字符串格式
         * 如果不進(jìn)行指定的話,默認(rèn)使用 yyyy-MM-dd'T'HH:mm:ss.SSS 格式
         */
        DateFormat dateFormat = new SimpleDateFormat(DateFormatPart.YYYYMMDD_HHMMSS_SLASH);
        jackson.setDateFormat(dateFormat);

        // 創(chuàng)建一個(gè)模塊,指定該模塊是用來(lái)解析 Date.class 類(lèi)型數(shù)據(jù)的
        SimpleModule newModule = new SimpleModule("GlobalDateDeserializer", PackageVersion.VERSION);
        // 將我們創(chuàng)建的全局日期轉(zhuǎn)換類(lèi)添加到模塊中,指定轉(zhuǎn)換Date類(lèi)型
        newModule.addDeserializer(Date.class, new CustomConfig.GlobalDateDeserializer());
        // 將該模塊添加到j(luò)ackson中
        jackson.registerModule(newModule);

        return jackson;
    }
}

三. 方式2-繼承StdDateFormat類(lèi),重寫(xiě)方法

  • parse方法用來(lái)將日期字符串轉(zhuǎn)換為Date(前臺(tái)向后臺(tái)傳數(shù)據(jù))
  • format方法用來(lái)將Date格式的數(shù)據(jù)轉(zhuǎn)換為指定格式的字符串(后臺(tái)向前臺(tái)傳數(shù)據(jù))。
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.fasterxml.jackson.databind.util.StdDateFormat;

public class GlobalJsonDateConvert extends StdDateFormat {

    // 靜態(tài)初始化final,共享
    public static final GlobalJsonDateConvert instance = new GlobalJsonDateConvert();

    // 日期字符串解析為日期
    @Override
    public Date parse(String dateStr, ParsePosition pos) {
        return getDate(dateStr);
    }

    @Override
    public Date parse(String dateStr) {
        return getDate(dateStr);
    }
	
	// 使用自定義的日期轉(zhuǎn)換工具類(lèi)將所有可能支持的日期字符串轉(zhuǎn)換為Date格式
    private Date getDate(String dateStr) {
        return DateUtil.formatDateStrToDateAllFormat(dateStr);
    }
    
	/*
   	 * 設(shè)置序列化時(shí)的默認(rèn)格式,即后臺(tái)返回?cái)?shù)據(jù)到前臺(tái)的時(shí)候,
     * Date類(lèi)型數(shù)據(jù)需要轉(zhuǎn)換為的字符串格式
     * 如果不進(jìn)行指定的話,默認(rèn)使用 yyyy-MM-dd'T'HH:mm:ss.SSS 格式
     */
    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition){
        SimpleDateFormat sdf = new SimpleDateFormat(DateFormatPart.YYYYMMDD_HHMMSS_SLASH);
        return sdf.format(date, toAppendTo, fieldPosition);
    }

    @Override
    public GlobalJsonDateConvert clone() {
        super.clone();
        return new GlobalJsonDateConvert();
    }
}

3.1 MappingJackson2HttpMessageConverter方式

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

@Configuration
public class CustomConfig {

    // JSON格式 全局日期轉(zhuǎn)換器配置
    @Bean
    public MappingJackson2HttpMessageConverter createMappingJackson2HttpMessageConverter() {

        /*
         * 通過(guò)MappingJackson2HttpMessageConverter得到的ObjectMapper,
         * 已經(jīng)默認(rèn)把 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 給關(guān)閉了
         */
        MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
        jacksonConverter.getObjectMapper().setDateFormat(GlobalJsonDateConvert.instance);

        return jacksonConverter;
    }
}

3.2 ObjectMapper方式

通過(guò)Jackson2ObjectMapperBuilder創(chuàng)建ObjectMapper對(duì)象,然后將我們定義的轉(zhuǎn)換器GlobalJsonDateConvert放到ObjectMapper對(duì)象中

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class CustomConfig {

    @Bean("objectMapper")
    @Primary
    @ConditionalOnMissingBean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
		
        ObjectMapper objectMapper = builder.build();
        objectMapper.setDateFormat(GlobalJsonDateConvert.instance);
        return objectMapper;
    }
}

3.3 Jackson2ObjectMapperBuilder方式

將我們定義的轉(zhuǎn)換器GlobalJsonDateConvert放到Jackson2ObjectMapperBuilder對(duì)象中

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class CustomConfig {

    @Bean
    public Jackson2ObjectMapperBuilder objectMapper() {

        Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder = new Jackson2ObjectMapperBuilder();
        jackson2ObjectMapperBuilder.dateFormat(GlobalJsonDateConvert.instance);
        return jackson2ObjectMapperBuilder;
    }
}

四. 效果

?前臺(tái)JS

// 向后臺(tái)傳輸?shù)膉son數(shù)據(jù)
const jsonData = {
	// ??待處理的日期字符串?dāng)?shù)據(jù)
    birthday: '2027年12月12日',
    nameAA: 'jiafeitian',
    hobby: '吃飯'
};

$.ajax({
    url: url,
    type: 'POST',
    // 對(duì)象轉(zhuǎn)換為json字符串
    data: JSON.stringify(jsonData),
    contentType: "application/json;charset=utf-8",
    success: function (data, status, xhr) {
        console.log(data);
    }
});

?后臺(tái)Form

import lombok.Data;
import java.util.Date;

@Data
public class Test15Form {

    private String name;

    private String hobby;

    private String address;
	
	// 用來(lái)接收的Date類(lèi)型的數(shù)據(jù)
    private Date birthday;
}

??可以看到前臺(tái)提交的日期字符串被轉(zhuǎn)換為Date格式了

五. 總結(jié)

方式一中的1種方法和方式二中的3種方法,共計(jì)4中方法都可以實(shí)現(xiàn)全局日期格式轉(zhuǎn)換器。
要點(diǎn)就是自定義日期轉(zhuǎn)換的工具類(lèi)用來(lái)處理各種可能的日期格式,并且將此工具類(lèi)放到Jackson中的ObjectMapper對(duì)象中,上述4中方法的本質(zhì)都是如此。

到此這篇關(guān)于SpringBoot JSON全局日期格式轉(zhuǎn)換器的文章就介紹到這了,更多相關(guān)SpringBoot JSON日期格式轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java源碼解析阻塞隊(duì)列ArrayBlockingQueue介紹

    Java源碼解析阻塞隊(duì)列ArrayBlockingQueue介紹

    今天小編就為大家分享一篇關(guān)于Java源碼解析阻塞隊(duì)列ArrayBlockingQueue介紹,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Spring?中使用?Validation?注解校驗(yàn)參數(shù)的方法

    Spring?中使用?Validation?注解校驗(yàn)參數(shù)的方法

    本文介紹了如何在Spring中使用Validation注解進(jìn)行參數(shù)校驗(yàn),包括引入依賴、簡(jiǎn)單示例、常見(jiàn)校驗(yàn)注解分類(lèi)與說(shuō)明、分組校驗(yàn)和自定義校驗(yàn),通過(guò)這些方法,可以方便地對(duì)Controller、Service等層面的參數(shù)進(jìn)行校驗(yàn),確保數(shù)據(jù)的合法性和一致性,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • SpringBoot配置Redis自定義過(guò)期時(shí)間操作

    SpringBoot配置Redis自定義過(guò)期時(shí)間操作

    這篇文章主要介紹了SpringBoot配置Redis自定義過(guò)期時(shí)間操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring,hibernate,struts經(jīng)典面試筆試題(含答案)

    Spring,hibernate,struts經(jīng)典面試筆試題(含答案)

    這篇文章主要介紹了Spring,hibernate,struts經(jīng)典面試筆試題極其參考含答案,涉及SSH基本概念,原理與使用技巧,需要的朋友可以參考下
    2016-03-03
  • 一文詳解JAVA中InputStreamReader流

    一文詳解JAVA中InputStreamReader流

    本文主要介紹了一文詳解JAVA中InputStreamReader流,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 詳解Java對(duì)象的強(qiáng)、軟、弱和虛引用+ReferenceQueue

    詳解Java對(duì)象的強(qiáng)、軟、弱和虛引用+ReferenceQueue

    這篇文章主要介紹了詳解Java對(duì)象的強(qiáng)、軟、弱和虛引用+ReferenceQueue的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • springboot?整合hbase的示例代碼

    springboot?整合hbase的示例代碼

    這篇文章主要介紹了springboot?整合hbase的示例代碼,本篇詳細(xì)總結(jié)了hbase的Java客戶端的使用,在實(shí)際開(kāi)發(fā)過(guò)程中,還需要結(jié)合自身的情況做更加細(xì)致的整合與優(yōu)化,需要的朋友可以參考下
    2022-04-04
  • SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證的流程

    SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證的流程

    Json web token (JWT), 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開(kāi)放標(biāo)準(zhǔn)((RFC 7519).這篇文章主要介紹了SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證,需要的朋友可以參考下
    2020-01-01
  • Spring框架生成圖片驗(yàn)證碼實(shí)例

    Spring框架生成圖片驗(yàn)證碼實(shí)例

    驗(yàn)證碼在很多地方都會(huì)遇到,實(shí)現(xiàn)的方法和形式也有很多,主要的目的就是為了安全,防止一些惡意的攻擊等。今天在之前搭建好的一個(gè)spring框架上寫(xiě)了一個(gè)驗(yàn)證碼的生成demo,我會(huì)貼出細(xì)節(jié)代碼,但是spring的配置就不在介紹了,有需要的可以參考借鑒。
    2016-08-08
  • java中線程的sleep()方法和yield()方法的區(qū)別

    java中線程的sleep()方法和yield()方法的區(qū)別

    本文主要介紹了java中線程的sleep()方法和yield()方法的區(qū)別,Thread類(lèi)的sleep()方法使線程休眠指定時(shí)間,不釋放鎖,而yield()提示調(diào)度器當(dāng)前線程愿意讓出CPU資源,不保證立即切換線程,感興趣的可以了解一下
    2024-10-10

最新評(píng)論

长垣县| 称多县| 临泉县| 兰西县| 芒康县| 全南县| 陈巴尔虎旗| 桐梓县| 扎兰屯市| 穆棱市| 祁东县| 盐池县| 天台县| 曲靖市| 偏关县| 浦东新区| 平江县| 偃师市| 渑池县| 邵阳市| 会同县| 津市市| 金溪县| 乌鲁木齐市| 许昌县| 星子县| 墨玉县| 衡南县| 遵化市| 隆尧县| 勐海县| 保德县| 吴堡县| 乌审旗| 美姑县| 昌乐县| 仪征市| 台中市| 泰州市| 衢州市| 隆安县|