01前言
由於mybatis提供也提供了外掛這個擴充套件,很多的思路就是在外掛上做文章,在github上也的確有這樣的倉庫。
基於Executor:
https://github.com/miaoxinwei/mybatis-crypt
基於StatementHandler:
https://github.com/ikchan/mybatis-plugin-cryptogram
這兩個分別是基於Executor和StatementHandler做的外掛,這裡不介紹怎麼實現一個mybatis外掛,有興趣的可以看下官網。
mybatis外掛plugins demo:
http://www.mybatis.org/mybatis-3/zh/configuration.html#plugins
分別可以對以下4種情況就行擴充套件:
ParameterHandler (getParameterObject, setParameters),aop setParameters是不行的,因為這時已經完成了sql解析,某些取值已經不會再透過原始的parameter取值。比如:如果時foreach標籤,在此時會通boundSql.getAdditionalParameter獲取
StatementHandler (prepare, parameterize, batch, update, query),這裡也是做不了的,因為已經失去了屬性註解相關的資訊
ResultSetHandler (handleResultSets, handleOutputParameters) 這個可以做結果集解密。
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) 這個當然是可以的,他就是查詢的出入口
所以在對資料做加減密的外掛時,選擇對Executor做。
這裡就實現一個基於Executor的Interceptor。在看到上面基於Executor實現時候,總感覺有些彆扭,
一是沒有將方法元資料與加解密分開,二是太多if else判斷在做加解密流程中。
新的實現將intercept方法分為以下4步
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
// 1.獲取方法加解密 元資料
MethodCryptMetadata methodCryptMetadata = getCachedMethodCryptMetaData((MappedStatement) args[0]);
// 2.加密
args[1] = methodCryptMetadata.encrypt(args[1]);
// 3.執行sql
Object returnValue = invocation.proceed();
// 4.解密
return methodCryptMetadata.decrypt(returnValue);
}
特殊說明
encryptWithOutAnnotation,decryptWithOutAnnotation可以透過外掛properties修改
程式碼中XXX標記的是特殊說明
關於bean的加密,會涉及到原物件的修改,程式碼中透過clone避免
為避免多處對null值就行判斷,handler和executor等都加了Null的實現
MethodMetadata中的兩個Resolver可能有一定的過度設計的嫌疑,主要是為了減少if else判斷
類圖、序列圖:
https://github.com/StarskyBoy/mybatis-crypt
01前言
由於mybatis提供也提供了外掛這個擴充套件,很多的思路就是在外掛上做文章,在github上也的確有這樣的倉庫。
基於Executor:
https://github.com/miaoxinwei/mybatis-crypt
基於StatementHandler:
https://github.com/ikchan/mybatis-plugin-cryptogram
02正文這兩個分別是基於Executor和StatementHandler做的外掛,這裡不介紹怎麼實現一個mybatis外掛,有興趣的可以看下官網。
mybatis外掛plugins demo:
http://www.mybatis.org/mybatis-3/zh/configuration.html#plugins
分別可以對以下4種情況就行擴充套件:
ParameterHandler (getParameterObject, setParameters),aop setParameters是不行的,因為這時已經完成了sql解析,某些取值已經不會再透過原始的parameter取值。比如:如果時foreach標籤,在此時會通boundSql.getAdditionalParameter獲取
StatementHandler (prepare, parameterize, batch, update, query),這裡也是做不了的,因為已經失去了屬性註解相關的資訊
ResultSetHandler (handleResultSets, handleOutputParameters) 這個可以做結果集解密。
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) 這個當然是可以的,他就是查詢的出入口
所以在對資料做加減密的外掛時,選擇對Executor做。
這裡就實現一個基於Executor的Interceptor。在看到上面基於Executor實現時候,總感覺有些彆扭,
一是沒有將方法元資料與加解密分開,二是太多if else判斷在做加解密流程中。
新的實現將intercept方法分為以下4步
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
// 1.獲取方法加解密 元資料
MethodCryptMetadata methodCryptMetadata = getCachedMethodCryptMetaData((MappedStatement) args[0]);
// 2.加密
args[1] = methodCryptMetadata.encrypt(args[1]);
// 3.執行sql
Object returnValue = invocation.proceed();
// 4.解密
return methodCryptMetadata.decrypt(returnValue);
}
特殊說明
encryptWithOutAnnotation,decryptWithOutAnnotation可以透過外掛properties修改
程式碼中XXX標記的是特殊說明
關於bean的加密,會涉及到原物件的修改,程式碼中透過clone避免
為避免多處對null值就行判斷,handler和executor等都加了Null的實現
MethodMetadata中的兩個Resolver可能有一定的過度設計的嫌疑,主要是為了減少if else判斷
03最後類圖、序列圖:
具體實現可見原始碼:
https://github.com/StarskyBoy/mybatis-crypt