欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot日期格式化及時(shí)差問(wèn)題分析

 更新時(shí)間:2022年12月10日 11:19:51   作者:寂寞旅行  
這篇文章主要介紹了springboot日期格式化,時(shí)差問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

提示:文章寫(xiě)完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔

前言

隨著mysql8.0的問(wèn)世,里面確實(shí)增加了很多功能,例如之前我發(fā)表的文章,數(shù)據(jù)庫(kù)層面的遞歸查詢等;不過(guò)也隨之而來(lái)帶來(lái)了一些不兼容的問(wèn)題,比如group by 報(bào)錯(cuò),還有就是日期時(shí)差問(wèn)題;

一、mysql中日期字段的正確設(shè)置

create_time timestamp default CURRENT_TIMESTAMP not null comment '創(chuàng)建時(shí)間',
update_time timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改時(shí)間'

創(chuàng)建時(shí)間會(huì)自動(dòng)獲取當(dāng)前時(shí)間
修改數(shù)據(jù)的時(shí)候,會(huì)自動(dòng)更新 修改時(shí)間,免去了每次程序都要設(shè)置的麻煩

二、日期格式化,時(shí)差

1. 日期字段返回格式不正確–方案一

例如一個(gè)實(shí)體中內(nèi)容如下

@Data
public class AAA{
   //創(chuàng)建時(shí)間
    private Date createTime;
    //修改時(shí)間
    private Date updateTime;
 }

這樣的話,返回的日期格式就錯(cuò)誤的,其次也會(huì)導(dǎo)致時(shí)間會(huì)早于數(shù)據(jù)庫(kù)的真正時(shí)間八小時(shí)。我們可以有兩種選擇,直接對(duì)當(dāng)前字段設(shè)置日期格式

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")//取日期時(shí)使用
   @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")//存日期時(shí)使用

也就是這樣

@Data
public class AAA{
   //創(chuàng)建時(shí)間
   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")//取日期時(shí)使用
   @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")//存日期時(shí)使用
    private Date createTime;
    //修改時(shí)間
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")//取日期時(shí)使用
   @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")//存日期時(shí)使用
    private Date updateTime;
 }

是不是很煩呀每次都要對(duì)每個(gè)實(shí)體類中的每個(gè)日期字段都添加

2.日期字段返回格式不正確–方案二

全局設(shè)置日期格式化的格式,并且全局聲名所有日期 的 補(bǔ)差 八小時(shí),設(shè)置yml即可

spring:
  profiles:
    active: dev
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

二、日期無(wú)法自動(dòng)填充

由于我已經(jīng)設(shè)置了創(chuàng)建時(shí)間的自動(dòng)填充,和修改時(shí)間的自動(dòng)修改,在數(shù)據(jù)庫(kù)層面已經(jīng)沒(méi)有問(wèn)題了,但是當(dāng)我用mybatis的時(shí)候,由于insertselective 等的字段非空判斷,導(dǎo)致就不會(huì)生成創(chuàng)建時(shí)間和修改時(shí)間;咋搞?

對(duì)于次問(wèn)題,我們通過(guò)攔截器,全局設(shè)置自動(dòng)填充日期等統(tǒng)一信息,還可以有創(chuàng)建人,修改人等;

1. mybatis-plus

由于mp提供了注解,我們可以通過(guò)設(shè)置一個(gè)注解就可以搞定填充問(wèn)題

@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

2. mybatis 只能靠自己了

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

/**
 * mybatis 攔截器字段自動(dòng)填充
 **/
@Slf4j
@Component
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class MybatisInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        log.debug("------sqlId------" + mappedStatement.getId());

        // sql類型:insert、update、select、delete
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameter = invocation.getArgs()[1];
        log.debug("------sqlCommandType------" + sqlCommandType);

        if (parameter == null) {
            return invocation.proceed();
        }

        // 當(dāng)sql為新增或更新類型時(shí),自動(dòng)填充操作人相關(guān)信息
        if (SqlCommandType.INSERT == sqlCommandType) {

            Field[] fields = getAllFields(parameter);
            for (Field field : fields) {
                try {
                    //注入創(chuàng)建時(shí)間
                    if ("createTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, new Date());
                        field.setAccessible(false);
                    }
                    //注入修改時(shí)間
                    if ("updateTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, new Date());
                        field.setAccessible(false);
                    }
                } catch (Exception e) {
                    log.error("failed to insert data, exception = ", e);
                }
            }
        }
        if (SqlCommandType.UPDATE == sqlCommandType) {

            Field[] fields = getAllFields(parameter);
            for (Field field : fields) {
                try {
                    if ("updateTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, new Date());
                        field.setAccessible(false);
                    }
                } catch (Exception e) {
                    log.error("failed to update data, exception = ", e);
                }
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // TODO Auto-generated method stub
    }

    /**
     * 獲取類的所有屬性,包括父類
     *
     * @param object
     * @return
     */
    private Field[] getAllFields(Object object) {
        Class<?> clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

}

1 MybatisInterceptor
2 MybatisConfiguration
廢話不多說(shuō),直接上代碼

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

/**
 * mybatis 攔截器字段自動(dòng)填充
 **/
@Slf4j
@Component
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class MybatisInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        log.debug("------sqlId------" + mappedStatement.getId());

        // sql類型:insert、update、select、delete
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameter = invocation.getArgs()[1];
        log.debug("------sqlCommandType------" + sqlCommandType);

        if (parameter == null) {
            return invocation.proceed();
        }

        // 當(dāng)sql為新增或更新類型時(shí),自動(dòng)填充操作人相關(guān)信息
        if (SqlCommandType.INSERT == sqlCommandType) {

            Field[] fields = getAllFields(parameter);
            for (Field field : fields) {
                try {
                    //注入創(chuàng)建時(shí)間
                    if ("createTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, new Date());
                        field.setAccessible(false);
                    }
                    //注入修改時(shí)間
                    if ("updateTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, new Date());
                        field.setAccessible(false);
                    }
                } catch (Exception e) {
                    log.error("failed to insert data, exception = ", e);
                }
            }
        }
        if (SqlCommandType.UPDATE == sqlCommandType) {

            Field[] fields = getAllFields(parameter);
            for (Field field : fields) {
                try {
                    if ("updateTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, new Date());
                        field.setAccessible(false);
                    }
                } catch (Exception e) {
                    log.error("failed to update data, exception = ", e);
                }
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // TODO Auto-generated method stub
    }

    /**
     * 獲取類的所有屬性,包括父類
     *
     * @param object
     * @return
     */
    private Field[] getAllFields(Object object) {
        Class<?> clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

}
/**
 * mybatis 攔截器注入
 **/
@Configuration
public class MybatisConfiguration {

    /**
     * 注冊(cè)攔截器
     */
    @Bean
    public MybatisInterceptor getMybatisInterceptor() {
        return new MybatisInterceptor();
    }
}

總結(jié)

如上就解決了大部分項(xiàng)目中時(shí)間的問(wèn)題,歡迎討論,咨詢~~

到此這篇關(guān)于springboot日期格式化,時(shí)差問(wèn)題的文章就介紹到這了,更多相關(guān)springboot日期格式化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis中ResultMap與多表查詢的處理方法

    MyBatis中ResultMap與多表查詢的處理方法

    這篇文章主要介紹了MyBatis中ResultMap與多表查詢的處理方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • 詳解java中的6種單例寫(xiě)法及優(yōu)缺點(diǎn)

    詳解java中的6種單例寫(xiě)法及優(yōu)缺點(diǎn)

    在java中,單例有很多種寫(xiě)法,面試時(shí),手寫(xiě)代碼環(huán)節(jié),除了寫(xiě)算法題,有時(shí)候也會(huì)讓手寫(xiě)單例模式,這里記錄一下單例的幾種寫(xiě)法和優(yōu)缺點(diǎn)。需要的朋友可以參考下
    2018-11-11
  • java學(xué)習(xí)指南之字符串與正則表達(dá)式

    java學(xué)習(xí)指南之字符串與正則表達(dá)式

    在日常Java后端開(kāi)發(fā)過(guò)程中,免不了對(duì)數(shù)據(jù)字段的解析,自然就少不了對(duì)字符串的操作,這其中就包含了正則表達(dá)式這一塊的內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于java學(xué)習(xí)指南之字符串與正則表達(dá)式的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • Java中Scanner的常用方法總結(jié)(一次學(xué)懂)

    Java中Scanner的常用方法總結(jié)(一次學(xué)懂)

    這篇文章主要給大家介紹了關(guān)于Java中Scanner常用方法的相關(guān)資料,Java中的Scanner是一個(gè)用于讀取用戶輸入的類,它可以讀取各種類型的數(shù)據(jù),包括整數(shù)、浮點(diǎn)數(shù)、字符串等等,需要的朋友可以參考下
    2023-11-11
  • Java環(huán)境變量的設(shè)置方法(圖文教程)

    Java環(huán)境變量的設(shè)置方法(圖文教程)

    想要成功配置Java的環(huán)境變量,那肯定就要安裝JDK,才能開(kāi)始配置的。
    2013-05-05
  • Java超詳細(xì)分析抽象類和接口的使用

    Java超詳細(xì)分析抽象類和接口的使用

    在類中沒(méi)有包含足夠的信息來(lái)描繪一個(gè)具體的對(duì)象,這樣的類稱為抽象類,接口是Java中最重要的概念之一,它可以被理解為一種特殊的類,不同的是接口的成員沒(méi)有執(zhí)行體,是由全局常量和公共的抽象方法所組成,本文給大家介紹Java抽象類和接口,感興趣的朋友一起看看吧
    2022-04-04
  • 使用jxls自定義命令設(shè)置動(dòng)態(tài)行高

    使用jxls自定義命令設(shè)置動(dòng)態(tài)行高

    這篇文章主要介紹了使用jxls自定義命令設(shè)置動(dòng)態(tài)行高,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java開(kāi)發(fā)validate方法中校驗(yàn)工具類詳解

    java開(kāi)發(fā)validate方法中校驗(yàn)工具類詳解

    這篇文章主要為大家介紹了java開(kāi)發(fā)validate方法中校驗(yàn)工具類詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • SpringMVC中處理靜態(tài)資源的過(guò)程詳解

    SpringMVC中處理靜態(tài)資源的過(guò)程詳解

    本文給大家介紹SpringMVC中處理靜態(tài)資源的過(guò)程,結(jié)合示例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-11-11
  • servlet之session工作原理簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    servlet之session工作原理簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了servlet之session工作原理簡(jiǎn)介,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07

最新評(píng)論