成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MyBatis 攔截器,帶你輕松搞定數據脫敏!

數據庫 其他數據庫
MyBatis 攔截器是一種插件機制,用于在 MyBatis 執行 SQL 語句時對其進行攔截、修改或增強。攔截器可以插入到 MyBatis 的執行過程中的不同位置,從而實現自定義的行為,例如記錄日志、修改 SQL 查詢、增強性能等。

1. 引言

1.1 什么是 MyBatis 攔截器

MyBatis 攔截器是一種插件機制,用于在 MyBatis 執行 SQL 語句時對其進行攔截、修改或增強。攔截器可以插入到 MyBatis 的執行過程中的不同位置,從而實現自定義的行為,例如記錄日志、修改 SQL 查詢、增強性能等。

  • 定義:MyBatis 攔截器是一種自定義插件,可以通過它攔截 MyBatis 核心組件(如 Executor、StatementHandler、ParameterHandler、ResultSetHandler)的方法調用。通過攔截器,我們可以在不修改 MyBatis 源碼的情況下,改變其行為或增強其功能。
  • 功能:

修改 SQL 語句,例如根據某些業務規則動態拼接 SQL。

記錄 SQL 執行日志、性能監控,統計執行時間等。

控制事務或實現緩存邏輯等。

1.2 為什么使用攔截器

使用 MyBatis 攔截器的主要原因是需要在不修改核心代碼的情況下,靈活地擴展 MyBatis 的功能。常見的應用場景包括:

  • 日志記錄:通過攔截器記錄每個 SQL 語句的執行情況,包括 SQL 本身、執行時間、返回結果等信息,用于后期分析和調試。
  • SQL 性能監控:攔截器可以用于統計 SQL 執行的時間,從而評估 SQL 的性能。長時間執行的 SQL 可以被識別出來,作為性能優化的目標。
  • 修改 SQL 語句:通過攔截器可以動態修改 SQL 語句,例如,在查詢中動態插入條件、修改排序規則,或者添加分頁邏輯。
  • 事務控制:在執行 SQL 操作之前、之后,或者在某些異常發生時,攔截器可以用來增強事務管理。

2. MyBatis 攔截器工作原理

2.1 攔截器的核心概念

MyBatis 攔截器工作時,核心組件是 Invocation、Interceptor、Method 和 Target 對象等:

  • Interceptor:這是所有自定義攔截器的接口,MyBatis 會根據配置找到并調用實現該接口的類。
  • Invocation:封裝了方法調用的對象,它包含了目標方法的信息以及方法的參數。通過 Invocation 對象,我們可以對方法的執行進行控制。
  • Method:表示目標方法,它是通過反射來獲取的。
  • Target:表示目標對象,它是被攔截的對象。例如,Executor、StatementHandler 等都是目標對象,攔截器會通過 Target 對象來訪問和控制這些對象的行為。

2.2 攔截器的生命周期

MyBatis 中,攔截器的生命周期通常包含三個階段:

  1. 插件初始化:當 MyBatis 啟動時,它會加載并初始化所有配置的攔截器。這時,攔截器會準備好攔截邏輯。
  2. 攔截執行:當 MyBatis 執行某個 SQL 語句時,會觸發攔截器的 intercept() 方法,這時攔截器會獲取執行方法的參數,可以進行修改、增強或替換方法的執行。
  3. 插件銷毀:攔截器在 MyBatis 銷毀時會清理資源,釋放占用的內存或線程等。

2.3 目標對象和方法

在 MyBatis 中,主要有四個目標對象可以被攔截:

  • Executor:執行 SQL 語句的核心對象。它的 update()、query() 等方法負責執行實際的增、刪、改、查操作。
  • StatementHandler:處理 SQL 語句的對象。它負責將 SQL 語句和參數綁定,并將其傳遞給數據庫。
  • ResultSetHandler:處理 SQL 查詢結果的對象。它負責將從數據庫返回的 ResultSet 轉換為 Java 對象。
  • ParameterHandler:處理 SQL 參數綁定的對象。它負責將參數設置到 SQL 語句中。

3. MyBatis 攔截器的實現

這里小編會分享工作中實際的案例: 數據脫敏。

3.1 自定義脫敏注解

首先需要知曉具體是哪個類中的哪些屬性需要進行脫敏處理,因此,需要自定義注解來實現對需要脫敏的屬性進行標注。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Desensitization {
    StrategyEnum strategy();
}

3.2 脫敏策略

有了標注后,對于脫敏也會涉及到脫敏策略的問題。不同的屬性,應該對應不同的脫敏方式,例如,名字只保留姓氏,而身份證和電話號碼,則需要對中間的數字打碼。因此,在使用自定義注解進行標注的同時,也要指定這個屬性對應的脫敏策略,這里使用枚舉類枚舉出不同屬性對應的正則處理。

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum StrategyEnum {

    NAME(s -> s.replaceAll("([\\u4e00-\\u9fa5]{1})(.*)", "$1*")),
    ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")),
    PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
    ADDRESS(s -> s.replaceAll("(\\s{8})\\s{4}(\\s*)\\s{4})", "$1****$2****"));

    private final Desensitizer desensitizer;

}

3.3 脫敏執行者

對于脫敏處理還需要一個執行者,將屬性值和正則表達式進行匹配和替換,進而完成脫敏處理。這里我們利用了JDK8提供的一個非常好用的接口Fuction,它提供了apply方法,這個方法作用是為了實現函數映射,也就是將一個值轉換為另一個值。如果不了解的同學可以百度下 Fuction 接口。

import java.util.function.Function;

public interface Desensitizer extends Function<String, String> {
}

3.4 自定義數據脫敏攔截器

因為要對結果集進行脫敏處理,所以要攔截的對象肯定是ResultSetHandler,并且是第一個方法。(可以想一下為啥是第一個方法)

public interface ResultSetHandler {
    <E> List<E> handleResultSets(Statement var1) throws SQLException;

    <E> Cursor<E> handleCursorResultSets(Statement var1) throws SQLException;

    void handleOutputParameters(CallableStatement var1) throws SQLException;
}

來看下具體的實現:

import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.stream.Stream;

@Component
@Intercepts(@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = Statement.class))
public class DesensitizationPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 獲取結果集
        List<Object> records = (List<Object>) invocation.proceed();
        // 處理結果集
        records.forEach(this::desensitization);
        return records;
    }

    /**
     * 2 * 判斷哪些需要脫敏處理
     * 3 * @param source 脫敏之前的源對象
     * 4
     */
    private void desensitization(Object source) {
        // 反射獲取類型中的所有屬性,判斷哪個需要進行脫敏
        Class<?> sourceClass = source.getClass();
        MetaObject metaObject = SystemMetaObject.forObject(source);
        Stream.of(sourceClass.getDeclaredFields())
                .filter(field -> field.isAnnotationPresent(Desensitization.class))
                .forEach(field -> doDesensitization(metaObject, field));
    }

    /**
     * 2 * 真正的脫敏處理
     * 3 * @param metaObject
     * 4
     */
    private void doDesensitization(MetaObject metaObject, Field field) {
        String name = field.getName();
        Object value = metaObject.getValue(name);
        if (value != null && metaObject.getGetterType(name) == String.class) {
            Desensitization annotation = field.getAnnotation(Desensitization.class);
            StrategyEnum strategy = annotation.strategy();
            String apply = strategy.getDesensitizer().apply((String) value);
            metaObject.setValue(name, apply);
        }
    }
}

數據脫敏字段:

import com.example.cl.mybatisPlugin.Desensitization;
import com.example.cl.mybatisPlugin.StrategyEnum;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class User {
    private Long id;
    @Desensitization(strategy = StrategyEnum.NAME)
    private String name;
    private Integer age;
}

最后看下脫敏結果:

圖片圖片

4. 總結

根據上面的說明,我們來看看MyBatis 攔截器的優勢和不足

  • 優勢:

非侵入式:通過攔截器機制,不需要修改 MyBatis 源碼即可定制功能。

靈活性:可以在多個階段對 SQL 操作進行干預,從而實現豐富的功能。

  • 不足:

性能開銷:如果攔截器過多或者邏輯復雜,可能會導致性能下降。

調試困難:攔截器的執行過程較為隱式,調試時可能會遇到一定的困難。

因此,我們攔截器不能創建過多,如果攔截的對象同一個,那么我們可以將多個功能放到同一個攔截器當中,從而減少攔截器的創建。

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2025-01-02 10:10:51

2023-11-13 08:16:08

MySQL數據數據庫

2019-07-09 08:23:07

數據安全旅游網絡安全

2024-09-09 16:50:21

2024-08-29 08:58:30

JPA編寫數據操

2024-07-17 08:29:20

2025-03-11 08:34:22

2016-04-29 10:02:39

2009-06-24 16:00:00

2016-09-09 01:07:06

數據中心容量規劃數據中心

2009-09-27 17:37:32

Hibernate攔截

2025-02-28 08:14:53

2025-06-09 07:35:00

NumPy數據分析數組

2024-02-28 09:35:52

2023-09-05 08:58:07

2019-12-19 08:56:21

MybatisSQL執行器

2011-05-16 10:14:11

Hibernate

2022-03-24 09:13:54

Mybatis加密解密

2009-07-08 17:02:11

JDK實現調用攔截器

2011-11-21 14:21:26

SpringMVCJava框架
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产极品粉嫩美女呻吟在线看人 | 国产精品久久久久久av公交车 | www.青青草 | 精品久久久久久久久久久下田 | 久久国产精彩视频 | 91影院| 中文字幕一区二区三区四区 | 亚洲视频一区在线观看 | 亚洲成人一区二区 | 国产一区二区电影 | av免费在线观看网站 | 狠狠干天天干 | 91影院| 天堂一区在线观看 | 巨大黑人极品videos精品 | 久久亚洲精品国产精品紫薇 | 亚洲在线免费观看 | 久久精品 | 欧美一级特黄aaa大片在线观看 | 正在播放国产精品 | 欧美一区二区三区在线观看视频 | 男女羞羞免费网站 | 午夜看电影在线观看 | 亚洲不卡在线观看 | 中文字幕在线观看一区 | 国产成人精品一区二区三区在线 | 精品久久久久香蕉网 | 久久久久午夜 | 中文字幕1区 | 日韩精品在线观看视频 | 色天堂影院 | 毛片免费在线观看 | 亚洲 欧美 日韩在线 | 欧美视频精品 | 久草在线青青草 | 久久免费高清视频 | 天天干天天干 | 日韩av在线一区二区三区 | 欧美黄色性生活视频 | 丁香综合 | 久久久久久一区 |