起因
由于需要对数据库数据做脱敏处理,鉴于现有业务改造量,最终决定通过mybatis拦截器进行统一的处理。
问题
对于mybatis-plus的框架时,现有解决方案失效,经过DEBUG发现mybatis-plus将where条件中的参数名称做了二次封装 双层map保存了原始字段的value丢弃了 字段名称 占位符成了 #{ew.paramNameValuePairs.MPGENVAL}。
SQL样例
如上图所示,当采用QueryWrapper抒写sql时最中经过AbstractWrapper的 addCondition、formatSqlIfNeed api 源码入下图:
现象
此时我们通过mybatis拦截器是无法获取where条件中的字段名称的,只能解析sql,但是这样处理方式就复杂了。
解决方案
给官方提了isuser但是并未采纳,于是采用曲线救国之策略。自己实现QueryWrapper 继承mybatis-plus的,重写它的 addCondition api 将原始字段名称保留,并抽象新的接口Wrapper
wrapper接口代码:
public interface Wrapper {
List<String> list=new ArrayList<String>();
default List<String> getList(){
return list;
}
Object getParamNameValuePairsByKey(int name);
void setParamNameValuePairs(int name,Object key);
}
实现类代码如下:
public class QueryWrapper<T> extends com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T> implements Wrapper {
private static final String MP_GENERAL_PARAMNAME = "MPGENVAL";
@Override
protected QueryWrapper<T> instance() {
return null;
}
@Override
protected com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T> addCondition(boolean condition, String column, SqlKeyword sqlKeyword, Object val) {
list.add(column);
return super.addCondition(condition, column, sqlKeyword, val);
}
@Override
public Object getParamNameValuePairsByKey(int name) {
return super.getParamNameValuePairs().get(MP_GENERAL_PARAMNAME+name);
}
@Override
public void setParamNameValuePairs(int name, Object value) {
super.getParamNameValuePairs().put(MP_GENERAL_PARAMNAME+name,value);
}
}
拦截器中代码:
Object parameterObject = statementHandler.getBoundSql().getParameterObject();
if (parameterObject instanceof MapperMethod.ParamMap) {
MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) parameterObject;
if(paramMap.containsKey("ew") && paramMap.get("ew") instanceof Wrapper){
Wrapper wrapper=(Wrapper)paramMap.get("ew");
List<String> list = wrapper.getList();
Wrapper wrapper1 = (Wrapper)paramMap.get("param1");
for (int i = 0; i < list.size(); i++) {
Object paramNameValuePairsByKey = wrapper.getParamNameValuePairsByKey(i + 1);
for (String field : clientConfig.getFields()) {
if (list.get(i).equals(field)) {
if (!(list.get(i).startsWith("SM4:"))) {
//加密
String encValue = SM4Util.encryptString(paramNameValuePairsByKey.toString());
String prefix = "SM4:" + clientConfig.getDataKeyId() + ":" + encValue;
wrapper.setParamNameValuePairs(i+1,prefix);
wrapper1.setParamNameValuePairs(i+1,prefix);
}
}
}
}
paramMap.put("ew",wrapper);
paramMap.put("param1",wrapper1);
}else {
for (String field : clientConfig.getFields()) {
if (paramMap.containsKey(field)) {
if (!(paramMap.get(field).toString().startsWith("SM4:"))) {
Object value = paramMap.get(field);
//加密
String encValue = SM4Util.encryptString(value.toString());
String prefix = "SM4:" + clientConfig.getDataKeyId() + ":" + encValue;
paramMap.put(field, prefix);
}
}
}
}
}
最终完美解决了,欢迎关注个人公众号,一起讨论技术: