目录
一、项目简单搭建
demo结构,已经搭建了无数次了,懒的粘贴了 o(╥﹏╥)o
pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
二 、一个接口了、两大注解、四大对象
- 一个接口:Interceptor
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
default void setProperties(Properties properties) {
// NOP
}
}
- 四大对象
- Executor : 执行器 (拦截sql的处理逻辑)
- ParameterHandler : 参数处理
- ResultSetHandler: 结果集处理
- StatementHandler : sql 语法构建
三、脱敏插件开发
1、定义插件继承 Intercepter接口
指定拦截上述四大对象的哪个方法
@Component
@Intercepts(@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = Statement.class))
public class TuominPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
List<Object> res = (List<Object>) invocation.proceed();
res.forEach(this::tuomin);
return res;
}
private void tuomin(Object source) {
// 或者source的类型
Class<?> aClass = source.getClass();
MetaObject metaObject = SystemMetaObject.forObject(source);
//过滤出所有有脱敏注解的属性
Arrays.stream(aClass.getDeclaredFields()).filter(field -> field.isAnnotationPresent(Tuomin.class)).forEach(field -> {
String fieldName = field.getName();
Object fieldValue = metaObject.getValue(fieldName);
if (metaObject.getGetterType(fieldName) == String.class && fieldValue != null) {
Tuomin tuomin = field.getAnnotation(Tuomin.class);
TuominStrategy tuominStrategy = tuomin.tuominStrategy();
String tuominValue = tuominStrategy.getDesensitizer().apply((String) fieldValue);
metaObject.setValue(fieldName, tuominValue);
}
});
}
}
2、定义脱敏注解,标注在实体类的字段上
表明对哪个字段进行脱敏
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Tuomin {
TuominStrategy tuominStrategy();
}
3、定义脱敏策略
是一个枚举类,里面有个属性是函数式接口,表明对字段进行怎样的处理
public enum TuominStrategy {
USERNAME(s -> s.substring(0, 1) + "**");
private Desensitizer desensitizer;
TuominStrategy(Desensitizer desensitizer) {
this.desensitizer = desensitizer;
}
public Desensitizer getDesensitizer() {
return desensitizer;
}
}
public interface Desensitizer extends Function<String,String> {
}
4、测试
由测试可以看到脱敏成功