Oinone体系中是不需要针对模型写SQL的,默认提供了通用的数据管理器。在带来便利的情况下,也导致传统的sql审查就没办法开展。但是我们可以以技术的手段收集慢SQL和限制问题SQL执行。
-
慢SQL搜集目的:去发现非原则性问题的慢SQL,并进行整改
-
限制问题SQL执行:对应一些不规范的SQL系统上直接做限制,如果有特殊情况手动放开
一、发现慢SQL
这个功能并没有直接加入到oinone的版本中,需要业务自行写插件,插件代码如下。大家可以根据实际情况进行改造比如:
-
堆栈入口,例子中只是放了pamirs,可以根据实际情况改成业务包路径
-
对慢SQL的定义是5s还是3s,根据实际情况变
package pro.shushi.pamirs.demo.core.plugin;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
@Intercepts({
@Signature(type = Executor.class,method = "query",args = {MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class})
})
@Component
@Slf4j
public class SlowSQLAnalysisInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
long start = System.currentTimeMillis();
Object result = invocation.proceed();
long end = System.currentTimeMillis();
if (end - start > 10000) {//大于10秒
try {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StringBuffer slowLog = new StringBuffer();
slowLog.append(System.lineSeparator());
for (StackTraceElement element : stackTraceElements) {
if (element.getClassName().indexOf("pamirs") > 0) {
slowLog.append(element.getClassName()).append(":").append(element.getMethodName()).append(":").append(element.getLineNumber()).append(System.lineSeparator());
}
}
Object parameter = null;
if (invocation.getArgs().length > 1) {
parameter = invocation.getArgs()[1];
}
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
Configuration configuration = mappedStatement.getConfiguration();
String originalSql = showSql(configuration, boundSql);
originalSql = originalSql.replaceAll("\'", "").replace("\"", "");
log.warn("检测到的慢SQL为:" + originalSql);
log.warn("业务慢SQL入口为:" + slowLog.toString());
} catch (Throwable e1) {
//忽略
}
}
return result;
}
public String showSql(Configuration configuration, BoundSql boundSql) {
Object parameterObject = boundSql.getParameterObject();
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
if (parameterMappings.size() > 0 && parameterObject != null) {
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
for (ParameterMapping parameterMapping : parameterMappings) {
String propertyName = parameterMapping.getProperty();
if (metaObject.hasGetter(propertyName)) {
Object obj = metaObject.getValue(propertyName);
sql = sql.replaceFirst("\\?", getParameterValue(obj));
} else if (boundSql.hasAdditionalParameter(propertyName)) {
Object obj = boundSql.getAdditionalParameter(propertyName);
sql = sql.replaceFirst("\\?", getParameterValue(obj));
}
}
}
}
return sql;
}
private String getParameterValue(Object obj) {
String value = null;
if (obj instanceof String) {
value = "'" + obj.toString() + "'";
} else if (obj instanceof Date) {
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
value = "'" + formatter.format(obj) + "'";
} else {
if (obj != null) {
value = obj.toString();
} else {
value = "";
}
}
return value;
}
}
二、限制问题SQL
Oinone的非法SQL校验插件:IllegalSQLInterceptor
目前版本oinone并没有生效该非法SQL校验的拦截器,因为这个插件晚于业务加入,所以为了避免伙伴应用因为插件原因改造就放到下个版本去,后续业务系统升级版本的时候,需要注意这个点
Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9314.html
访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验