中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

徹底解決Springmvc中時(shí)間的轉(zhuǎn)換和序列化等問(wèn)題-創(chuàng)新互聯(lián)

痛點(diǎn)
在使用Spring mvc 進(jìn)行開(kāi)發(fā)時(shí)我們經(jīng)常遇到前端傳來(lái)的某種格式的時(shí)間字符串無(wú)法用java8的新特性java.time包下的具體類(lèi)型參數(shù)來(lái)直接接收。 我們使用含有java.time封裝類(lèi)型的參數(shù)接收也會(huì)報(bào)反序列化問(wèn)題,在返回前端帶時(shí)間類(lèi)型的同樣會(huì)出現(xiàn)一些格式化的問(wèn)題。今天我們來(lái)徹底解決他們。

為息烽等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及息烽網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、息烽網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

建議
其實(shí)最科學(xué)的建議統(tǒng)一使用時(shí)間戳來(lái)代表時(shí)間。這個(gè)是最完美的,避免了前端瀏覽器的兼容性問(wèn)題,同時(shí)也避免了其它一些中間件的序列化/反序列化問(wèn)題。但是用時(shí)間表達(dá)可能更清晰語(yǔ)義化。兩種方式各有千秋,如果我們堅(jiān)持使用java8的時(shí)間類(lèi)庫(kù)也不是沒(méi)有辦法。下面我們會(huì)以java.time.LocalDateTime為例逐一解決這些問(wèn)題。

局部注解方式
網(wǎng)上有很多文章說(shuō)該注解是前端指向后端的,也就是前端向后端傳遞時(shí)間參數(shù)格式化使用的,這沒(méi)有錯(cuò)!但是有一個(gè)小問(wèn)題,該方式只能適用于不涉及反序列化的情況下。也就是以下場(chǎng)景才適用:

@GetMapping("/local")
    public Map<String, String> data(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime localDateTime) {
        Map<String, String> map = new HashMap<>(1);
        map.put("data", localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        return map;
    }

如果你在下面這個(gè)場(chǎng)景使用就不行了:

@Data
public class UserInfo {

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthday;
    private String name;
    private Integer age;
}

   @PostMapping("/user")
    public Object postData(@RequestBody UserInfo userInfo) {
        System.out.println("userInfo = " + userInfo);
        return userInfo;
    }

原因是Post請(qǐng)求參數(shù)在body中,需要反序列化成對(duì)象。默認(rèn)是jackson類(lèi)庫(kù)來(lái)進(jìn)行反序列化,并不觸發(fā)@DateTimeFormat注解機(jī)制。這時(shí)我們就需要使用jackson的格式化注解@JsonFormat。我們將實(shí)體類(lèi)UserInfo改造成下面的就可以了:

@Data
public class UserInfo {
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime birthday;
    private String name;
    private Integer age;
}

以上兩個(gè)注解可以并存,但是一定要清楚各自的使用場(chǎng)景。這里還有一個(gè)小細(xì)節(jié):格式一定要對(duì)應(yīng)好時(shí)間類(lèi)型。比如yyyy-MM-dd 對(duì)應(yīng)java.time.LocalDate 。想再個(gè)性化一些@JsonFormat 可以被@JsonDeserialize和@JsonSerialize 代替。但是它們的using參數(shù)需要你自己實(shí)現(xiàn)為你對(duì)應(yīng)的時(shí)間類(lèi)型類(lèi)型。如果@JsonFormat、@JsonDeserialize和@JsonSerialize同時(shí)存在@JsonFormat的優(yōu)先級(jí)要更高。

局部處理的好處
局部處理的好處在于八個(gè)字:百花齊放,百家爭(zhēng)鳴 ??梢员3侄鄻有浴€(gè)性化 。但是局部帶來(lái)了一個(gè)新的問(wèn)題 :沒(méi)有共同的標(biāo)準(zhǔn) 、不兼容。進(jìn)而不方便維護(hù)。所以有時(shí)候基于業(yè)務(wù)需要我們?nèi)只梢越y(tǒng)一管理。下面我們將講解如何進(jìn)行全局化配置。

全局化化時(shí)間格式配置
全局化其實(shí)也是基于 @DateTimeFormat 和@JsonFormat 兩種場(chǎng)景來(lái)進(jìn)行配置。對(duì)于@DateTimeFormat的場(chǎng)景我們通過(guò)實(shí)現(xiàn)Spring提供的接口:

DateTimeFormatter :
     // 時(shí)間格式化
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA);

類(lèi)型轉(zhuǎn)換接口:

org.springframework.core.convert.converter.Converter&lt;S,T&gt;
實(shí)現(xiàn):

@Bean
    public Converter<String, LocalDateTime> localDateConverter() {
        return new Converter<String, LocalDateTime>() {
            @Override
            public LocalDateTime convert(String source) {
                return LocalDateTime.parse(source, FORMATTER);
            }
        };
    }

或者格式化接口:

org.springframework.format.Formatter&lt;T&gt;
實(shí)現(xiàn) :

@Bean
    public Formatter<LocalDateTime> localDateFormatter() {
        return new Formatter<LocalDateTime>() {
            @Override
            public LocalDateTime parse(String text, Locale locale) throws ParseException {
                return LocalDateTime.parse(text, FORMATTER);
            }

            @Override
            public String print(LocalDateTime object, Locale locale) {
                return object.format(FORMATTER);
            }
        };
    }

以上兩個(gè)接口的實(shí)現(xiàn)都要注冊(cè)為Spring Bean,配置的時(shí)候二者選其一即可,其中S即Source也就是來(lái)源,其實(shí)就是前端的時(shí)間字符串。T即Target也就是目標(biāo),代表你需要轉(zhuǎn)化或者格式化的時(shí)間java類(lèi)型。那么對(duì)于時(shí)間序列化和反序列化我們進(jìn)行如下配置就行了(基于默認(rèn)jackson,以L(fǎng)ocalDateTime 為例):

@Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {

        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder
                 // 反序列化
                .deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(FORMATTER))
                 // 序列化
                .serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(FORMATTER));
    }

同樣該jsonMapper自定義構(gòu)建器要注冊(cè)成Spring Bean才行。

全局配置要點(diǎn)

全局配置的一些優(yōu)缺點(diǎn)上面已經(jīng)闡述了,這里我還是要啰嗦一下要點(diǎn)避免你踩坑。全局配置跟局部配置一樣。同樣要約定pattern。這就要求我們?nèi)直3忠恢?。我們可以?shí)現(xiàn)多個(gè)以上的全局配置來(lái)對(duì)其他諸如LocalDate、OffsetDateTime 的適配。同時(shí)如果我們接入了其它一些需要用到序列化/反序列化的中間件,比如redis、rabbitmq,我們也要注意進(jìn)行適配。

總結(jié)

通過(guò)以上對(duì)時(shí)間格式的局部和全局處理方式的介紹,相信困擾你的Spring mvc 時(shí)間問(wèn)題不會(huì)再存在了。如果感覺(jué)寫(xiě)對(duì)可以請(qǐng)轉(zhuǎn)發(fā)告訴其他同學(xué),點(diǎn)個(gè)贊,關(guān)注一下

創(chuàng)新互聯(lián)www.cdcxhl.cn,專(zhuān)業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開(kāi)啟,新人活動(dòng)云服務(wù)器買(mǎi)多久送多久。

文章題目:徹底解決Springmvc中時(shí)間的轉(zhuǎn)換和序列化等問(wèn)題-創(chuàng)新互聯(lián)
標(biāo)題來(lái)源:http://m.rwnh.cn/article8/coihop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT網(wǎng)站營(yíng)銷(xiāo)、網(wǎng)站導(dǎo)航、靜態(tài)網(wǎng)站App設(shè)計(jì)、云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)
梅河口市| 永嘉县| 金沙县| 安徽省| 抚远县| 丽水市| 兴安县| 茌平县| 开封市| 平潭县| 安阳市| 谷城县| 凤庆县| 宜章县| 万山特区| 保康县| 潼关县| 博客| 丰原市| 津南区| 芮城县| 湾仔区| 建始县| 夏邑县| 紫金县| 蒙阴县| 田阳县| 仁寿县| 获嘉县| 罗江县| 石家庄市| 宝山区| 清镇市| 富源县| 安龙县| 丹东市| 太原市| 托克逊县| 元江| 东乡| 嘉义市|