91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么通過MyBatis自定義插件實現簡易數據權限

發布時間:2021-09-07 10:46:28 來源:億速云 閱讀:208 作者:chen 欄目:大數據

這篇文章主要講解了“怎么通過MyBatis自定義插件實現簡易數據權限”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么通過MyBatis自定義插件實現簡易數據權限”吧!

1.mybatis自定義插件

一說到mybatis插件,都會想到mybatis的分頁插件。的確現在開發中用mybatis的話,一般都會用到它。它能在我們的sql語句后面添加分頁查詢條件,達到分頁查詢的效果。

①配置

由于mybatis是基于xml插件配置的所以,我們要在xml中配置自己的插件

<plugins>
    <plugin interceptor="com.wj.Interceptor.DataScopeInterceptor" /> //自定義插件的全類名
</plugins>
②接口的攔截

先看看一張圖 ,mybatis主要提供了下面4個接口支持攔截 怎么通過MyBatis自定義插件實現簡易數據權限
編寫DataScopeInterceptor(需要實現Interceptor接口)

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DataScopeInterceptor implements Interceptor {
    // 這里是每次執行操作的時候,都會進行這個攔截器的方法內
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //TODO:自已的業務處理
        return invocation.proceed();
    }
    // 主要是為了把這個攔截器生成一個代理放到攔截器鏈中
    @Override
    public Object plugin(Object o) {

        return Plugin.wrap(o, this);
    }

    // 插件初始化的時候調用,也只調用一次,插件配置的屬性從這里設置進來
    @Override
    public void setProperties(Properties properties) {

    }
}

看看這個注解

@Signature(
    type = StatementHandler.class, //這是指攔截哪個接口
    method = "prepare", //這個是攔截接口中的什么方法,可以在StatementHandler中找到此方法
    args = {Connection.class, Integer.class}//攔截方法的參數列表)

下面我們啟動項目,執行sql查詢的時候會進入到我們的插件中。現在算是自己定義好了一個空的插件了。

ps:mybatis可以同時定義多個插件,這些插件采用責任鏈模式,通過代理對象一個一個調用下一個插件,進行執行。

2.數據權限(僅以查詢為例)

項目開發中,大多項目都有權限相關的考慮,說到權限,大體分為兩類,數據權限與功能權限。數據權限一般是針對不同的角色或者用戶,查詢到不同的數據,對同一數據表或者數據源的不同條件篩選。而功能權限更多是對功能菜單的訪問權限。在不同項目中,權限設計也不同,跟系統業務,架構設計息息相關,做好權限,是非常困難的。我這里僅僅是對數據權限的一個模擬。不涉及具體實現。(這塊本來就沒有同一的處理方案)。

①授權的分類

我這里將數據權限分為兩個類別,明細授權,條件授權
明細授權:對一個表數據,通過id進行授權,比如有個商品表,可以把指定商品的id授權給指定用戶或角色,達到該用戶或角色可以查詢到這一個指定商品。

select * from product where id = 1

條件授權:可以通過指定范圍查詢條件為某一用戶或角色進行授權

select * from product where name like '%iphone%'

上面的兩個sql很明顯的表現了這兩種授權方式的區別與聯系。我們不免會想,明細授權也可以用條件授權來實現,達到相同的效果,的確是這樣,我們這里僅僅說明兩天不同的授權方式,其實在真實的環境中,可能還會有其他的授權形式。

上面我們通過對mybatis插件的自定義,我們就可以對sql進行處理了。所以,數據權限無非就是在自定義插件中獲取到sql。在sql語句后面拼接不同的過濾條件來達到數據過濾。真實業務場景更為復雜。很多時候,不僅僅是拼接這么簡單。對sql的處理也是一件廢功夫的事情。下面看具體實現

②不同授權類型實現

數據權限接口,這里只寫了一個getsql的方法定義,參數為原始sql,返回值為經過處理后的sql

public interface DataScopeInterface {

    /**
     * 獲取sql
     * @return
     */
    String getSql(String sql);

}

DataScopeInterface有兩個不同的實現類,明細與條件

@Component("grantDataScope")
@Slf4j
public class GrantDataScope implements DataScopeInterface {
    //明細授權實現
    @Override
    public String getSql(String sql) {
        //這里是獲取當前登錄用戶的id,我定義了一個登錄攔截器,通過ThreadLocal保存當前登錄的用戶。代碼就不寫出來了。比較簡單
        String userId = LoginHandlerInterceptor.userLoginThreadLocal.get();
        //這里模擬用戶id為1的用戶在查詢語句后面拼接id為1的過濾條件
        if("1".equals(userId)){
            if(sql.toLowerCase().contains("where")){
                sql += ">

條件授權

@Component("ruleDataScope")
@Slf4j
public class RuleDataScope implements DataScopeInterface {
    // 條件授權實現
    public String getSql(String sql) {
        String userId = LoginHandlerInterceptor.userLoginThreadLocal.get();
        //模擬用戶為id為2的用戶加name中有ipone的數據
        if("2".equals(userId)){
            if(sql.toLowerCase().contains("where")){
                sql += " and name like '%iphone%'";
            }else {
                sql += " where name like '%iphone%'";
            }
        }
        log.info("rule: "+ sql);
        return sql;
    }
}
③插件邏輯實現

下面在自定義插件中編寫業務具體實現邏輯。由于我們不同的授權類型都是交給spring管理的bean,我們可以借此通過策略模式來實現授權規則的可擴展性。有不同的授權規則只需要實現DataScopeInterface接口即可。

public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
        String userName = LoginHandlerInterceptor.userLoginThreadLocal.get();
        //  sql語句類型
        Object sqlCommandType = metaStatementHandler.getValue("delegate.mappedStatement.sqlCommandType");
        //只考慮了查詢
        if (SqlCommandType.SELECT.equals(sqlCommandType)) {
            //獲取sql
            String sql = String.valueOf(metaStatementHandler.getValue("delegate.boundSql.sql"));
            //獲取DataScopeInterface的實現類集合,并循環執行sql的格式化
            Map<String, DataScopeInterface> dataScopeInterfaceMap = SpringContextUtils.getBeanOfType(DataScopeInterface.class);
            Collection<DataScopeInterface> dataScopeInterfaces = dataScopeInterfaceMap.values();
            for (DataScopeInterface dataScopeInterface : dataScopeInterfaces) {
                sql = dataScopeInterface.getSql(sql);
            }
            log.info("sql --> " + sql);
            //重新設置sql
            metaStatementHandler.setValue("delegate.boundSql.sql", sql);
        }
        return invocation.proceed();
}
⑤驗證

啟動項目,模擬用戶id為1的用戶登錄,返回了一條記錄,達到了過濾的效果。

2019-08-24 14:07:05,496 DEBUG (BaseJdbcLogger.java:145)- ==>  Preparing: select * from product where id = 1 
2019-08-24 14:07:05,496 DEBUG (BaseJdbcLogger.java:145)- ==> Parameters: 
2019-08-24 14:07:05,498 DEBUG (BaseJdbcLogger.java:145)- <==      Total: 1

同理,模擬用戶id為2的用戶登錄。返回兩條記錄

2019-08-24 14:09:59,006 DEBUG (BaseJdbcLogger.java:145)- ==>  Preparing: select * from product where where name like '%iphone%' 
2019-08-24 14:09:59,017 DEBUG (BaseJdbcLogger.java:145)- ==> Parameters: 
2019-08-24 14:09:59,020 DEBUG (BaseJdbcLogger.java:145)- <==      Total: 2
⑥真實業務場景下的考慮的問題

大概的簡易數據權限就這樣了,下面多談談在真實業務場景下的一些情況:
1,不同的授權類型都是在數據庫中進行維護,在不同的實現中,讀取數據庫的權限配置信息,進而封裝sql
2,存在多表關聯的時候,或非驅動表控制了數據權限,驅動表沒有控制,根據不同的業務場景具體分析,對sql的處理也就更加困難了。
3,在分布式中存在跨系統問題的數據權限控制。得看情況,做方案。

感謝各位的閱讀,以上就是“怎么通過MyBatis自定義插件實現簡易數據權限”的內容了,經過本文的學習后,相信大家對怎么通過MyBatis自定義插件實現簡易數據權限這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

桃园市| 金昌市| 长武县| 涞水县| 东乡| 无极县| 车致| 元谋县| 灌南县| 项城市| 玉溪市| 神池县| 平南县| 拜城县| 岫岩| 砀山县| 怀化市| 彝良县| 天峻县| 锡林郭勒盟| 瑞安市| 兰考县| 宁德市| 仙桃市| 南丰县| 庄河市| 广灵县| 韩城市| 蒙山县| 淳安县| 临潭县| 凤凰县| 林甸县| 博野县| 兴义市| 东宁县| 万山特区| 孟州市| 大关县| 铅山县| 马尔康县|