目錄
?
1、問題引入
2、 基本功能實(shí)現(xiàn)
3、功能完善
3.1 ThreadLocal
3.1.1 介紹
3.1.2 常用方法
3.2 思路分析
3.3 代碼實(shí)現(xiàn)
1、問題引入
在我們的項(xiàng)目開發(fā)中,我們會(huì)發(fā)現(xiàn)有一些數(shù)據(jù)庫表字段是每個(gè)表都有的,例如 : 創(chuàng)建時(shí)間,創(chuàng)建人 ,更新時(shí)間,更新人。
而我們目前的針對(duì)這些字段我們的目前的處理方式就是 增加或者修改的時(shí)候一個(gè)一個(gè)的去賦值。
如果都按照上面的方法進(jìn)行操作的話,那我們就需要在每個(gè)業(yè)務(wù)方法中進(jìn)行操作,這樣會(huì)不會(huì)顯得我們的代碼過于冗余、繁瑣。
這個(gè)時(shí)候我們就可以使用Mybatis Plus提供的公共字段自動(dòng)填充功能。
2、 基本功能實(shí)現(xiàn)
Mybatis Plus公共字段自動(dòng)填充,也就是在插入或者更新的時(shí)候?yàn)橹付ㄗ侄钨x予指定的值,使用它的好處就是可以統(tǒng)一對(duì)這些字段進(jìn)行處理,避免了重復(fù)代碼。
在上述的問題分析中,我們提到有四個(gè)公共字段,需要在新增/更新中進(jìn)行賦值操作, 具體情況如下:
字段名 |
賦值時(shí)機(jī) |
說明 |
createTime |
插入(INSERT) |
當(dāng)前時(shí)間 |
updateTime |
插入(INSERT) , 更新(UPDATE) |
當(dāng)前時(shí)間 |
createUser |
插入(INSERT) |
當(dāng)前登錄用戶ID |
updateUser |
插入(INSERT) , 更新(UPDATE) |
當(dāng)前登錄用戶ID |
接下來我們就開始編寫代碼。
首先第一步就是在實(shí)體類的屬性上加入 @TableField 注解,指定自動(dòng)填充的策略。
注 :
fill : 字段自動(dòng)填充策略
添加好注解后,我們就需要按照框架要求編寫元數(shù)據(jù)對(duì)象處理器這樣的一個(gè)類,在此類中統(tǒng)一為公共字段賦值,注意!此類需要實(shí)現(xiàn)MetaObjectHandler接口。
創(chuàng)建好類,我們就可以開始編寫操作代碼了。
3、功能完善
細(xì)心的朋友已經(jīng)發(fā)現(xiàn),我們上面只填充了時(shí)間,并沒有填充創(chuàng)建人和更新人,現(xiàn)在我們就來完善一下。
本來我想的是,我登錄的時(shí)候是將用戶id存入了HttpSession中,現(xiàn)在我從HttpSession中獲取不就行了?
但是 ,MyMetaObjectHandler類中是不能直接獲得HttpSession對(duì)象的,所以我們需要通過其他方式來獲取登錄用戶id。
這里我們使用JAVA 給我們提供的一個(gè)類,ThreadLocal。
在了解 ThreadLocal 之前我們先了解當(dāng)我們?cè)谠黾樱薷膯T工信息時(shí), 我目前項(xiàng)目業(yè)務(wù)的執(zhí)行流程是什么樣子的,如下圖:
客戶端發(fā)送的每次http請(qǐng)求,對(duì)應(yīng)的在服務(wù)端都會(huì)分配一個(gè)新的線程來處理,在處理過程中涉及到下面類中的方法都屬于相同的一個(gè)線程:
- LoginCheckFilter (登錄過濾器) 的doFilter方法
- Controller的方法
- MyMetaObjectHandler的insertFill/updateFill方法
我們可以在上述類的方法中加入如下代碼(獲取當(dāng)前線程ID,并輸出):
long id = Thread.currentThread().getId();
log.info("線程id為:{}",id);
執(zhí)行功能進(jìn)行驗(yàn)證,通過觀察控制臺(tái)輸出可以發(fā)現(xiàn),一次請(qǐng)求對(duì)應(yīng)的線程id是相同的。
3.1 ThreadLocal
3.1.1 介紹
ThreadLocal并不是一個(gè)Thread,而是Thread的局部變量。當(dāng)使用ThreadLocal維護(hù)變量時(shí),ThreadLocal為每個(gè)使用該變量的線程提供獨(dú)立的變量副本,所以每一個(gè)線程都可以獨(dú)立地改變自己的副本,而不會(huì)影響其它線程所對(duì)應(yīng)的副本。
ThreadLocal為每個(gè)線程提供單獨(dú)一份存儲(chǔ)空間,具有線程隔離的效果,只有在線程內(nèi)才能獲取到對(duì)應(yīng)的值,線程外則不能訪問當(dāng)前線程對(duì)應(yīng)的值。
3.1.2 常用方法
public void set(T value) |
設(shè)置當(dāng)前線程的線程局部變量的值 |
public T get() |
返回當(dāng)前線程所對(duì)應(yīng)的線程局部變量的值 |
public void remove() |
刪除當(dāng)前線程所對(duì)應(yīng)的線程局部變量的值 |
3.2 思路分析
- 我們可以先在LoginCheckFilter(登錄過濾器) 的doFilter方法中獲取當(dāng)前登錄用戶id。并調(diào)用ThreadLocal的set方法來設(shè)置當(dāng)前線程的線程局部變量的值(用戶id)。
- 在MyMetaObjectHandler的insertFill/updateFill方法中調(diào)用ThreadLocal的get方法來獲得當(dāng)前線程所對(duì)應(yīng)的線程局部變量的值(用戶id)。
- 如果在后續(xù)的操作中, 我們需要在Controller / Service中要使用當(dāng)前登錄用戶的ID, 可以直接從ThreadLocal直接獲取。
3.3 代碼實(shí)現(xiàn)
首先為了使用方便,我們可以編寫一個(gè)基于ThreadLocal封裝的工具類,主要get 和 set 方法。
/**
* @description: 基于ThreadLocal封裝工具類,用戶保存和獲取當(dāng)前登錄用戶id
* @author: Jie
* @date: 2022/8/12 14:18
**/
public class BaseContext {
private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
/**
* @description: 設(shè)置值
* @author: Jie
* @date: 2022/8/12 14:18
* @param: [id] 線程id
**/
public static void setCurrentId(Long id){
threadLocal.set(id);
}
/**
* @description: 獲取值
* @author: Jie
* @date: 2022/8/12 14:18
**/
public static Long getCurrentId(){
return threadLocal.get();
}
}
然后在LoginCheckFilter(登錄過濾器)的doFilter方法中調(diào)用BaseContext來設(shè)置當(dāng)前登錄用戶的id。
接下來我們就可以 在MyMetaObjectHandler的方法中調(diào)用BaseContext獲取登錄用戶的id。文章來源:http://www.zghlxwxcb.cn/news/detail-446290.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-446290.html
到了這里,關(guān)于Mybatis Plus 公共字段自動(dòng)填充功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!