فهرست منبع

新增SQL拦截打印日志插件

DESKTOP-VAEGFGM\zqc 1 سال پیش
والد
کامیت
f36d62dd84

+ 27 - 0
menduner/menduner-im-biz/src/main/java/com/citu/module/menduner/im/controller/app/base/wukong/ChannelDeleteReqVo.java

@@ -0,0 +1,27 @@
+package com.citu.module.menduner.im.controller.app.base.wukong;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ChannelDeleteReqVo {
+    @JsonProperty("channel_id")
+    private String channelId;
+
+    @JsonProperty("channel_type")
+    private Integer channelType;
+
+    public String getChannelId() {
+        return channelId;
+    }
+
+    public void setChannelId(String channelId) {
+        this.channelId = channelId;
+    }
+
+    public Integer getChannelType() {
+        return channelType;
+    }
+
+    public void setChannelType(Integer channelType) {
+        this.channelType = channelType;
+    }
+}

+ 1 - 1
menduner/menduner-im-biz/src/main/java/com/citu/module/menduner/im/framework/security/config/SecurityConfiguration.java

@@ -1,7 +1,7 @@
 package com.citu.module.menduner.im.framework.security.config;
 
 import com.citu.framework.security.config.AuthorizeRequestsCustomizer;
-import com.citu.module.system.enums.ApiConstants;
+import com.citu.module.menduner.im.enums.ApiConstants;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;

+ 0 - 23
menduner/menduner-im-biz/src/main/java/com/citu/module/menduner/im/interceptor/WuKongWuKongApiInterceptor.java

@@ -1,23 +0,0 @@
-//package com.citu.module.menduner.im.interceptor;
-//
-//import com.alibaba.excel.util.StringUtils;
-//import com.citu.module.menduner.im.MendunerIMApplication;
-//import feign.RequestInterceptor;
-//import feign.RequestTemplate;
-//
-//public class WuKongWuKongApiInterceptor implements RequestInterceptor {
-//
-//    private String uri;
-//
-//
-//    @Override
-//    public void apply(RequestTemplate requestTemplate) {
-//        if(StringUtils.isBlank(uri)){
-//            uri =  MendunerIMApplication.applicationContext.getEnvironment().getProperty("im.wulong.url");
-//        }
-//        requestTemplate.uri(uri);
-//
-//
-//        System.out.println(requestTemplate);
-//    }
-//}

+ 144 - 0
menduner/menduner-im-biz/src/main/java/com/citu/module/menduner/im/mybatis/plugin/SqlInterceptor.java

@@ -0,0 +1,144 @@
+package com.citu.module.menduner.im.mybatis.plugin;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.apache.ibatis.type.TypeHandlerRegistry;
+
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * 1.可以用来分析SQL执行效率
+ * 2.可以用来获取实际执行的SQL
+ */
+
+@Intercepts({
+        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
+        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
+        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})}
+)
+@Slf4j
+public class SqlInterceptor implements Interceptor {
+//    private static final Log log = LogFactory.getLog(SqlInterceptor.class);    
+    /**
+     * 最小打印时间 sql时间超过这个值才打印日志 毫秒
+     **/
+    private int MIN_SIZE = 0;
+
+    @Override
+    public Object intercept(Invocation invocation) throws Throwable {
+        // 判断是否需要执行插件,避免浪费性能
+        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
+        Object parameter = null;
+        if (invocation.getArgs().length > 1) {
+            parameter = invocation.getArgs()[1];
+        }
+        String sqlId = mappedStatement.getId();
+        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
+        Configuration configuration = mappedStatement.getConfiguration();
+
+        long startTime = System.currentTimeMillis();
+        Object result = null;
+        try {
+            result = invocation.proceed();
+        } finally {
+            try {
+                long sqlCostTime = System.currentTimeMillis() - startTime;
+                String sql = getSql(configuration, boundSql);
+                formatSqlLog(mappedStatement.getSqlCommandType(), sqlId, sql, sqlCostTime, result);
+            } catch (Exception ignored) {
+                log.error("SQL插件执行失败 Mapper:{} 参数对象:{}", sqlId, JSON.toJSONString(boundSql.getParameterObject()), ignored);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public Object plugin(Object target) {
+        return Plugin.wrap(target, this);
+    }
+
+    @Override
+    public void setProperties(Properties properties) {
+        if (properties == null) {
+            return;
+        }
+        if (properties.containsKey("minLogSize")) {
+            MIN_SIZE = Integer.valueOf(properties.getProperty("minLogSize"));
+        }
+    }
+
+    private String getSql(Configuration configuration, BoundSql boundSql) {
+        // 输入sql字符串空判断
+        String sql = boundSql.getSql();
+        if (StrUtil.isBlank(sql)) {
+            return "";
+        }
+
+        //去掉换行符
+        sql = sql.replaceAll("[\\s\n ]+", " ");
+
+        //填充占位符, 目前基本不用mybatis存储过程调用,故此处不做考虑
+        Object parameterObject = boundSql.getParameterObject();
+        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
+        if (!parameterMappings.isEmpty() && parameterObject != null) {
+            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
+            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
+                sql = this.replacePlaceholder(sql, 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 = replacePlaceholder(sql, obj);
+                    } else if (boundSql.hasAdditionalParameter(propertyName)) {
+                        Object obj = boundSql.getAdditionalParameter(propertyName);
+                        sql = replacePlaceholder(sql, obj);
+                    }
+                }
+            }
+        }
+        return sql;
+    }
+
+    private String replacePlaceholder(String sql, Object parameterObject) {
+        String result;
+        if (parameterObject == null) {
+            result = "NULL";
+        } else if (parameterObject instanceof String) {
+            result = String.format("'%s'", parameterObject.toString());
+        } else if (parameterObject instanceof Date) {
+            result = String.format("'%s'", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(parameterObject));
+        } else {
+            result = parameterObject.toString();
+        }
+        return sql.replaceFirst("\\?", result);
+    }
+
+    private void formatSqlLog(SqlCommandType sqlCommandType, String sqlId, String sql, long costTime, Object obj) {
+        if (costTime > MIN_SIZE) {
+            if (sqlCommandType == SqlCommandType.UPDATE || sqlCommandType == SqlCommandType.INSERT || sqlCommandType == SqlCommandType.DELETE) {
+                log.info("[执行时长{}ms] [{}] {}; 影响行数:{}", costTime, sqlId, sql, obj);
+            }
+            if (sqlCommandType == SqlCommandType.SELECT) {
+                log.info("[执行时长{}ms] [{}] {}; 结果行数:{}", costTime, sqlId, sql, null==obj?"无":((Collection<?>) obj).size());
+            }
+        }
+    }
+}

+ 9 - 0
menduner/menduner-im-biz/src/main/java/com/citu/module/menduner/im/service/wukong/WuKongApiService.java

@@ -30,6 +30,15 @@ public interface WuKongApiService {
     @PostMapping("/channel/messagesync")
     public ChannelMessageSyncResp channelMessageSync(@RequestBody ChannelMessageSyncReqVo reqVo);
 
+    /**
+     * 删除频道
+     * @param reqVo
+     * @return
+     */
+
+    @PostMapping("/channel/delete")
+    public ChannelMessageSyncResp channelDelete(@RequestBody ChannelDeleteReqVo reqVo);
+
     @PostMapping("/conversations/setUnread")
     public WukongApiResp   conversationsSetUnread(@RequestBody ConversationsUnreadReqVo reqVo);