Mybatis插件的实现
Mybatis插件开发(一个接口四大对象)
与其说是插件,不如说是拦截器更准确,其主要步骤就是实现interceptor接口,然后实现其中的intercept方法,
这里面的Invocation参数里面的proceed方法就是具体执行SQL的方法。
拦截只要是拦截四大对象:
1、Executor:拦截的是具体的update、querry等方法
2、ParameterHandler 参数处理
3、ResultSetHandler sql语法构建
4、StatementHandler sql语法构建
开发一款脱敏插件
需求:将表中的某些敏感字段变为***,只显示最后一个字符
建立user表
package com.mybatis.mybatisplugin.plugin;
import org.springframework.stereotype.Repository;
import java.io.Serializable;
import java.util.Date;
/**
* @author:
* @date:2022/3/6
*/
@Repository
public class User implements Serializable {
private static final long serialVersionUID = -40356785423868312L;
/**
* 主键
*/
private Long id;
/**
* 用户名
*/
@Tuomin(type = TuominType.USERNAME)
private String userName;
/**
* 昵称
*/
private String nickName;
/**
* 密码
*/
private String password;
/**
* 账号状态(0正常 1停用)
*/
private String status;
/**
* 邮箱
*/
private String email;
/**
* 手机号
*/
private String phonenumber;
/**
* 用户性别(0男,1女,2未知)
*/
private String sex;
/**
* 头像
*/
private String avatar;
/**
* 用户类型(0管理员,1普通用户)
*/
private String userType;
/**
* 创建人的用户id
*/
private Long createBy;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新人
*/
private Long updateBy;
/**
* 更新时间
*/
private Date updateTime;
/**
* 删除标志(0代表未删除,1代表已删除)
*/
private Integer delFlag;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", nickName='" + nickName + '\'' +
", password='" + password + '\'' +
", status='" + status + '\'' +
", email='" + email + '\'' +
", phonenumber='" + phonenumber + '\'' +
", sex='" + sex + '\'' +
", avatar='" + avatar + '\'' +
", userType='" + userType + '\'' +
", createBy=" + createBy +
", createTime=" + createTime +
", updateBy=" + updateBy +
", updateTime=" + updateTime +
", delFlag=" + delFlag +
'}';
}
}
建立枚举类,因为脱敏的方式有很多种,这里我只有一种
package com.mybatis.mybatisplugin.plugin;
/**
* @author:
* @date:2022/5/26
*/
public enum TuominType{
USERNAME(s -> s.replaceAll("\\S{2}","**"));
;
private final Desensitizer desensitizer;
TuominType(Desensitizer d) {
this.desensitizer = d;
}
public Desensitizer getDesensitizer() {
return desensitizer;
}
}
里面的Desensitizer继承了Function接口
package com.mybatis.mybatisplugin.plugin;
import java.util.function.Function;
/**
* @author:
* @date:2022/5/26
*/
public interface Desensitizer extends Function<String,String> {
}
创建注解类,只能在属性上标注,被注解的属性字段就有脱敏功能
package com.mybatis.mybatisplugin.plugin;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author:
* @date:2022/5/26
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Tuomin{
TuominType type();
}
创建具体的脱敏类,实现interceptor接口
package com.mybatis.mybatisplugin.plugin;
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.apache.ibatis.session.ResultHandler;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.stream.Stream;
/**
* @author:
* @date:2022/5/25
*/
@Intercepts(@Signature(type = ResultSetHandler.class,method = "handleResultSets",args = Statement.class))
@Component
public class TuominPlugin implements Interceptor {
@Override
public Object intercept(final Invocation invocation) throws Throwable {
List<Object> proceed = (List<Object>) invocation.proceed();
proceed.forEach(this::tuomin);
return proceed;
}
private void tuomin(final Object source) {
Class<?> sourceClass = source.getClass();
MetaObject metaObject = SystemMetaObject.forObject(source);
Stream.of(sourceClass.getDeclaredFields())
.filter(filed->filed.isAnnotationPresent(Tuomin.class))
.forEach(field -> doTuomin(metaObject,field));
}
private void doTuomin(final MetaObject metaObject, final Field field) {
String name = field.getName();
Object value = metaObject.getValue(name);
if(String.class == metaObject.getGetterType(name) && value !=null)
{
//拿到脱敏注解本身
Tuomin annotation = field.getAnnotation(Tuomin.class);
TuominType type = annotation.type();
Object o = type.getDesensitizer().apply((String) value);
System.out.println(o);
metaObject.setValue(name,o);
}
}
}
测试效果: