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

SpringBoot ThreadLocal實現(xiàn)公共字段自動填充案例講解

 更新時間:2022年10月12日 11:39:39   作者:懶羊羊.java  
每一次在Controller層中封裝改動數(shù)據(jù)的方法時都要重新設(shè)置一些共性字段,顯得十分冗余。為了解決此問題也是在項目中第一次利用到線程,總的來說還是讓我眼前一亮,也開闊了視野,對以后的開發(fā)具有深遠的意義

一.字段自動填充引入

先看一個現(xiàn)象,在之前寫好的表中,我們發(fā)現(xiàn)有很多字段重復(fù)出現(xiàn)

比如update_time、create_time、create_user…

這就導(dǎo)致需要在Controller層中每一次對表中數(shù)據(jù)進行修改后調(diào)用一次.setCreateTime(LocalDateTime.now());或者setUpdateTime(LocalDateTime.now());等等“硬編碼問題又出現(xiàn)了”顯得格外麻煩

這些共性字段如何統(tǒng)一拿出來處理呢?MyBatisPlus給了我們解決方案,為了實現(xiàn)這一功能:

首先

我們需要在公共字段對應(yīng)的實體屬性上加上@TableField注解與指定填充策略,就像這樣:

    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;

不難看出,fill的類型是一個枚舉類

若是不需要處理則選擇DEAFULT,若是增添后需要修改字段的值選擇INSERT,若是涉及修改數(shù)據(jù)時需要修改字段的值則選擇UPDATE,若是插入和修改都需要設(shè)置字段的值則選擇INSERT_UPDATE就像updateTime和updateUser,只要涉及對數(shù)據(jù)的操作就要修改字段的值

類似于全局異常處理器,為了實現(xiàn)字段填充也需要定義一個元數(shù)據(jù)對象處理器

二.元數(shù)據(jù)對象處理器

在定義的類中實現(xiàn)MetaObjecthandler接口,并重寫接口中策略對應(yīng)的方法,就像這樣:

@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自動填充...");
        log.info(metaObject.toString());
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自動填充...");
        log.info(metaObject.toString());
    }
}

這里有點像繼承HttpServlet那個套路,重寫doGet()與doPost()方法,要實現(xiàn)什么功能就寫在對應(yīng)的方法里…

重寫完方法,不妨debug一下:

發(fā)現(xiàn)我實現(xiàn)接口后在方法里拿到了實體的數(shù)據(jù),并封裝到了形參里的metaObject對象中,接下來我就可以利用此對象來做公共字段的集中處理了!

所謂的自動填充也正是因為該類擁有@Component注解,在每一次的項目啟動后就會被掃描到,加載到,而類中的方法又實現(xiàn)了功能,所以才可以做到自動填充字段!

回到正題

我們要做的是把公共的字段做到統(tǒng)一填充,具體實現(xiàn)則是在重寫的方法里調(diào)用setValue()方法并傳進去字段與參數(shù),就像這樣:

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自動填充...");
        log.info(metaObject.toString());
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自動填充...");
        log.info(metaObject.toString());
        metaObject.setValue("updateTime",LocalDateTime.now());
    }

相比之前controller層中的employee.setCreateTime(LocalDateTime.now());/employee.setUpdateTime(LocalDateTime.now());來看還是比較好理解,無非就是“茴“字的另一種寫法

(但卻實現(xiàn)了一勞永逸)…

可能有人會問,懶羊羊你的updateUser與createUser字段怎么不處理呢?

確實,還記得之前在controller層中我們是怎么處理的嗎?

為了確定User是誰,我們從Session里拿到了操作的對象id,并調(diào)用set方法修改了對象的字段值

按照上面的經(jīng)驗,為了能夠動態(tài)的拿到id,我們應(yīng)該這樣設(shè)置:

可是,在此方法中metaObject對象好像不能利用Session里的empID,那要如何獲得對象的標(biāo)識呢?

不就是一個標(biāo)識么,我用線程id可以嗎?

三.Threadlocal的使用

在這之前,需要明白一點,每當(dāng)客戶端發(fā)送一次HTTP請求,對應(yīng)在服務(wù)器端會分配一個新的線程來處理。項目設(shè)計到現(xiàn)在為止,以點擊一次保存按鈕作為一次請求,它會觸發(fā)過濾器、調(diào)用Controller層、MetaObjectHandler層的方法

我們通過Thread的內(nèi)部方法:long id = Thread.currentThread().getId();來獲得當(dāng)前線程的id,以日志的形式log.info("當(dāng)前線程id:{}",id);輸出到控制臺:

可見,三者的線程id相同,說明他們在同一個線程中,這就保證了一致性,也正是因為這個特性,所以可用來當(dāng)作表中的字段id使用來作為標(biāo)識

在此基礎(chǔ)上,大致方向已經(jīng)敲定是利用線程的特性,具體要如何實現(xiàn)呢?那就不得不需要了解一下ThreadLocal這個概念了:

1.ThreadLocal并不是一個Thread,而是Thread的局部變量。

2.當(dāng)使用ThreadLocal維護變量時,ThreadLocal為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應(yīng)的副本。

3.ThreadLocal為每個線程提供單獨一份存儲空間,具有線程隔離的效果,只有在線程內(nèi)才能獲取到對應(yīng)的值,線程外則不能訪問

常用方法

public void set(T value)設(shè)置當(dāng)前線程局部變量的值
public T get()返回當(dāng)前線程所對應(yīng)的線程局部變量的值

了解到ThreadLocal特性,我們就可以結(jié)合“同一線程”這一特性來獲得那個對象唯一的SessionId。

?? 在前面的登錄功能中我們設(shè)置了一個filter,在filter中我們已經(jīng)拿到過了一次SessionId,寫到這里解決方案不就出來了嘛——把filter中的SessionId當(dāng)作參數(shù)傳給ThreadLocal的set方法,然后在MetaObjectHandler實現(xiàn)類(元數(shù)據(jù)對象處理器)中調(diào)用ThreadLocal的get()方法得到SessionId

就像這樣:

1.為了規(guī)范,我們封裝一個類,功能是調(diào)用ThreadLocal的方法

/**
 * 基于ThreadLocal封裝工具類,用于保護和獲取當(dāng)前登錄id
 */
public class BaseContext {
    private static ThreadLocal<Long> threadLocal=new ThreadLocal();
    public static void setCurrentId(Long currentId){
        threadLocal.set(currentId);
    }
    public static Long getCurrentId(){
        return threadLocal.get();
    }
}

2.在filter中做到SessionId的遷移

3.在MetaObjectHandler實現(xiàn)類中利用SessionId完成公共字段填充設(shè)置

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自動填充...");
        log.info(metaObject.toString());
        long id = Thread.currentThread().getId();
        log.info("當(dāng)前線程id:{}",id);
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("createUser",BaseContext.getCurrentId());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }

這樣,就可以一勞永逸咯~

又是一個小技巧?。?/p>

到此這篇關(guān)于SpringBoot ThreadLocal實現(xiàn)公共字段自動填充案例講解的文章就介紹到這了,更多相關(guān)SpringBoot自動填充內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java如何從不規(guī)則的字符串中截取出日期

    java如何從不規(guī)則的字符串中截取出日期

    這篇文章主要介紹了java從不規(guī)則的字符串中截取出日期的方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • druid升級后sql監(jiān)控頁面為空白的解決

    druid升級后sql監(jiān)控頁面為空白的解決

    這篇文章主要介紹了druid升級后sql監(jiān)控頁面為空白的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • springboot多模塊中的共用配置文件詳解

    springboot多模塊中的共用配置文件詳解

    這篇文章主要介紹了springboot多模塊中的共用配置文件詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java自帶定時任務(wù)ScheduledThreadPoolExecutor實現(xiàn)定時器和延時加載功能

    Java自帶定時任務(wù)ScheduledThreadPoolExecutor實現(xiàn)定時器和延時加載功能

    今天小編就為大家分享一篇關(guān)于Java自帶定時任務(wù)ScheduledThreadPoolExecutor實現(xiàn)定時器和延時加載功能,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • spring學(xué)習(xí)之util:properties的使用

    spring學(xué)習(xí)之util:properties的使用

    這篇文章主要介紹了spring學(xué)習(xí)之util:properties的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java8 自定義CompletableFuture的原理解析

    Java8 自定義CompletableFuture的原理解析

    這篇文章主要介紹了Java8 自定義CompletableFuture的原理解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringMVC源碼之HandlerMapping處理器映射器解析

    SpringMVC源碼之HandlerMapping處理器映射器解析

    這篇文章主要介紹了SpringMVC源碼之HandlerMapping處理器映射器解析,在Spring?MVC中,HandlerMapping處理器映射器用于確定請求處理器對象,請求處理器可以是任何對象,只要它們使用了@Controller注解或注解@RequestMapping,需要的朋友可以參考下
    2023-08-08
  • 關(guān)于Java集合框架面試題(含答案)上

    關(guān)于Java集合框架面試題(含答案)上

    Java集合框架為Java編程語言的基礎(chǔ),也是Java面試中很重要的一個知識點。這里,我列出了一些關(guān)于Java集合的重要問題和答案。
    2015-12-12
  • Java 8中日期和時間的處理方法

    Java 8中日期和時間的處理方法

    Java 8新增了LocalDate和LocalTime接口,接下來通過本文給大家介紹Java 8中日期和時間的處理方法,非常不錯,感興趣的朋友一起看下吧
    2016-08-08
  • Java中接口的多態(tài)詳解

    Java中接口的多態(tài)詳解

    大家好,本篇文章主要講的是Java中接口的多態(tài)詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-02-02

最新評論

林西县| 曲周县| 隆子县| 宜川县| 迭部县| 乐至县| 吉首市| 泰和县| 红河县| 将乐县| 黔西县| 拉萨市| 武穴市| 乡城县| 宁陵县| 道孚县| 金川县| 确山县| 汉川市| 尼勒克县| 文安县| 乌什县| 郎溪县| 临汾市| 成安县| 焦作市| 云林县| 隆德县| 广州市| 休宁县| 洪江市| 阳信县| 宁强县| 刚察县| 白朗县| 竹溪县| 韶关市| 安阳市| 桃园市| 多伦县| 瓮安县|