中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot?JSON全局日期格式轉換器如何實現

發布時間:2023-04-17 15:16:03 來源:億速云 閱讀:171 作者:iii 欄目:開發技術

這篇文章主要講解了“SpringBoot JSON全局日期格式轉換器如何實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“SpringBoot JSON全局日期格式轉換器如何實現”吧!

    需求

    前臺有日期字符串的數據,提交到后臺。后臺實體類使用Date屬性接收。
    日期字符串有多種格式,需要用一個轉換器將合法的日期字符串格式轉換為Date類型。

    分析

    當前臺的提交數據的Content-Typeapplication/json;charset=utf-8,后臺使用@RequestBody來接收數據的時候,使用此轉換方式。

    一. 前期準備

    1.1 日期正則注解

    用來標記日期字符串所對應的正則表達式

    import java.lang.annotation.*;
    
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    public @interface DatePattern {
    	
        String value();
    }

    1.2 日期格式定數

    指定所有支持的日期格式

    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 日期轉換工具類

    • 從日期格式定數類中獲取所有的屬性值和該屬性上所標記的正則注解,通過反射來映射為map。

    • 如果有需要增刪的日期格式的話,只需要修改日期格式定數即可,便于維護。

    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可以避免按照順序匹配正則表達式
        private static final Map<String, String> datePatternMap = new LinkedHashMap<>();
    
        // 日期格式List
        private static final List<String> dateFormatList = new ArrayList<>();
    
        // 使用靜態代碼塊,可以保證只初始化一次
        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;
                }
    
                //  強制讓屬性可以訪問
                ReflectionUtils.makeAccessible(field);
    
                // 日期格式化字符串
                String dateFormatStr = "";
                try {
                    // 獲取當前屬性所對應的屬性值
                    dateFormatStr = (String)field.get(dateFormatClass);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
    
                dateFormatList.add(dateFormatStr);
    
                // 將該屬性的屬性值和屬性上的正則表達式放到map中
                datePatternMap.put(dateFormatStr, annotation.value());
            }
        }
    	
    	// 用所有可能支持的格式將日期字符串轉換為Date格式
        public static Date formatDateStrToDateAllFormat(String dateStr) {
    
            if (ObjectUtils.isEmpty(dateStr)) {
                return null;
            }
    
            try {
                for (Map.Entry<String, String> mapEntry : datePatternMap.entrySet()) {
    				
    				// 如果當前日期字符串不符合當前正則的話
                    if (!dateStr.matches(mapEntry.getValue())) {
                        continue;
                    }
    
                    return DateUtil.formatStringToDate(dateStr, mapEntry.getKey());
                }
            } catch (ParseException e) {
                return null;
            }
    
            return null;
        }
    	
    	// 通過指定的格式將日期字符串轉換為Date類型
        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類,重寫_parseDate方法

    • 該方式的要點是通過繼承DateDeserializer類,然后重寫_parseDate方法實現轉換功能

    • 自定義的GlobalDateDeserializer類需要添加到自定義的SimpleModule模塊中,然后將模塊添加到ObjectMapper中,通過jackson來實現轉換。

    • 通過設置ObjectMapper對象的setDateFormat方法來實現后臺數據返回到前臺時的Date轉String的默認格式。

    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 {
    
        /*
         * 自定義的全局的日期轉換解析類,需要繼承jackson包中的DateDeserializer
         * 因為此類不會在別的地方使用了,因此直接使用內部類聚合到自定義的配置文件中
         */
        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) {
    
            // 創建jackson對象
            ObjectMapper jackson = builder.createXmlMapper(false).build();
    
            /*
             * DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
             * 在進行序列化或者反序列化的時候,
             * JSON字符串中有一個字段,但是我們的對象沒有這個字段的時候,該怎么處理
             * 設置為true的時候,會拋出異常
             * 設置為false,忽略異常繼續處理
             */
            jackson.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            // 禁用默認的「yyyy-MM-dd'T'HH:mm:ss.SSS」UTC類型
            jackson.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    
             /*
             * 設置序列化時的默認格式,即后臺返回數據到前臺的時候,
             * Date類型數據需要轉換為的字符串格式
             * 如果不進行指定的話,默認使用 yyyy-MM-dd'T'HH:mm:ss.SSS 格式
             */
            DateFormat dateFormat = new SimpleDateFormat(DateFormatPart.YYYYMMDD_HHMMSS_SLASH);
            jackson.setDateFormat(dateFormat);
    
            // 創建一個模塊,指定該模塊是用來解析 Date.class 類型數據的
            SimpleModule newModule = new SimpleModule("GlobalDateDeserializer", PackageVersion.VERSION);
            // 將我們創建的全局日期轉換類添加到模塊中,指定轉換Date類型
            newModule.addDeserializer(Date.class, new CustomConfig.GlobalDateDeserializer());
            // 將該模塊添加到jackson中
            jackson.registerModule(newModule);
    
            return jackson;
        }
    }

    三. 方式2-繼承StdDateFormat類,重寫方法

    • parse方法用來將日期字符串轉換為Date(前臺向后臺傳數據)

    • format方法用來將Date格式的數據轉換為指定格式的字符串(后臺向前臺傳數據)。

    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 {
    
        // 靜態初始化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);
        }
    	
    	// 使用自定義的日期轉換工具類將所有可能支持的日期字符串轉換為Date格式
        private Date getDate(String dateStr) {
            return DateUtil.formatDateStrToDateAllFormat(dateStr);
        }
        
    	/*
       	 * 設置序列化時的默認格式,即后臺返回數據到前臺的時候,
         * Date類型數據需要轉換為的字符串格式
         * 如果不進行指定的話,默認使用 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格式 全局日期轉換器配置
        @Bean
        public MappingJackson2HttpMessageConverter createMappingJackson2HttpMessageConverter() {
    
            /*
             * 通過MappingJackson2HttpMessageConverter得到的ObjectMapper,
             * 已經默認把 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 給關閉了
             */
            MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
            jacksonConverter.getObjectMapper().setDateFormat(GlobalJsonDateConvert.instance);
    
            return jacksonConverter;
        }
    }

    3.2 ObjectMapper方式

    通過Jackson2ObjectMapperBuilder創建ObjectMapper對象,然后將我們定義的轉換器GlobalJsonDateConvert放到ObjectMapper對象中

    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方式

    將我們定義的轉換器GlobalJsonDateConvert放到Jackson2ObjectMapperBuilder對象中

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

    四. 效果

    ?前臺JS

    // 向后臺傳輸的json數據
    const jsonData = {
    	// ????待處理的日期字符串數據
        birthday: '2027年12月12日',
        nameAA: 'jiafeitian',
        hobby: '吃飯'
    };
    
    $.ajax({
        url: url,
        type: 'POST',
        // 對象轉換為json字符串
        data: JSON.stringify(jsonData),
        contentType: "application/json;charset=utf-8",
        success: function (data, status, xhr) {
            console.log(data);
        }
    });

    ?后臺Form

    import lombok.Data;
    import java.util.Date;
    
    @Data
    public class Test15Form {
    
        private String name;
    
        private String hobby;
    
        private String address;
    	
    	// 用來接收的Date類型的數據
        private Date birthday;
    }

    可以看到前臺提交的日期字符串被轉換為Date格式了

    SpringBoot?JSON全局日期格式轉換器如何實現

    感謝各位的閱讀,以上就是“SpringBoot JSON全局日期格式轉換器如何實現”的內容了,經過本文的學習后,相信大家對SpringBoot JSON全局日期格式轉換器如何實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    奉贤区| 柳林县| 惠东县| 平潭县| 海丰县| 屏南县| 雷山县| 贡嘎县| 应用必备| 大理市| 紫云| 湘潭县| 渭源县| 岑溪市| 公安县| 上高县| 鄂尔多斯市| 灵台县| 嘉祥县| 宝丰县| 呼伦贝尔市| 延吉市| 天等县| 遵义市| 乌拉特中旗| 花垣县| 定州市| 宣化县| 梓潼县| 吉木萨尔县| 山东省| 保亭| 赞皇县| 孟津县| 东山县| 广东省| 余江县| 安达市| 乐都县| 武胜县| 新津县|