001/* 002 * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.audit; 017 018import com.mybatisflex.core.mybatis.TypeHandlerObject; 019import com.mybatisflex.core.util.ClassUtil; 020import com.mybatisflex.core.util.SqlUtil; 021 022import java.io.Serializable; 023import java.lang.reflect.Array; 024import java.lang.reflect.Proxy; 025import java.sql.PreparedStatement; 026import java.sql.SQLException; 027import java.sql.Statement; 028import java.util.ArrayList; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033/** 034 * SQL 审计详细消息。 035 */ 036public class AuditMessage implements Serializable { 037 038 /** 039 * 平台,或者是运行的应用。 040 */ 041 private String platform; 042 043 /** 044 * 应用模块。 045 */ 046 private String module; 047 048 /** 049 * 执行这个 SQL 涉及的 URL 地址。 050 */ 051 private String url; 052 053 /** 054 * 自定义业务 ID。 055 */ 056 private String bizId; 057 058 /** 059 * 执行这个 SQL 涉及的平台用户。 060 */ 061 private String user; 062 063 /** 064 * 执行这个 SQL 的平台用户 IP 地址。 065 */ 066 private String userIp; 067 068 /** 069 * 执行这个 SQL 的服务器 IP 地址。 070 */ 071 private String hostIp; 072 073 /** 074 * SQL 内容。 075 */ 076 private String query; 077 078 /** 079 * SQL 参数。 080 */ 081 private List<Object> queryParams; 082 083 /** 084 * SQL 查询出来数据的数量。 085 */ 086 private int queryCount; 087 088 /** 089 * SQL 执行的时间点(当前时间,毫秒)。 090 */ 091 private long queryTime; 092 093 /** 094 * SQL 执行的消耗时间(毫秒)。 095 */ 096 private long elapsedTime; 097 098 /** 099 * MappedStatement ID 100 */ 101 private String stmtId; 102 103 /** 104 * 数据库名称。 105 */ 106 private String dsName; 107 108 /** 109 * 其他扩展元信息。 110 */ 111 private Map<String, Object> metas; 112 113 public String getPlatform() { 114 return platform; 115 } 116 117 public void setPlatform(String platform) { 118 this.platform = platform; 119 } 120 121 public String getModule() { 122 return module; 123 } 124 125 public void setModule(String module) { 126 this.module = module; 127 } 128 129 public String getUrl() { 130 return url; 131 } 132 133 public void setUrl(String url) { 134 this.url = url; 135 } 136 137 public String getBizId() { 138 return bizId; 139 } 140 141 public void setBizId(String bizId) { 142 this.bizId = bizId; 143 } 144 145 public String getUser() { 146 return user; 147 } 148 149 public void setUser(String user) { 150 this.user = user; 151 } 152 153 public String getUserIp() { 154 return userIp; 155 } 156 157 public void setUserIp(String userIp) { 158 this.userIp = userIp; 159 } 160 161 public String getHostIp() { 162 return hostIp; 163 } 164 165 public void setHostIp(String hostIp) { 166 this.hostIp = hostIp; 167 } 168 169 public String getQuery() { 170 return query; 171 } 172 173 public void setQuery(String query) { 174 this.query = query; 175 } 176 177 public List<Object> getQueryParams() { 178 return queryParams; 179 } 180 181 public void setQueryParams(List<Object> queryParams) { 182 this.queryParams = queryParams; 183 } 184 185 public void addParams(Statement statement, Object... objects) { 186 if (queryParams == null) { 187 queryParams = new ArrayList<>(); 188 } 189 190 for (Object object : objects) { 191 if (object != null && ClassUtil.isArray(object.getClass())) { 192 for (int i = 0; i < Array.getLength(object); i++) { 193 Object value = Array.get(object, i); 194 if (value instanceof Map) { 195 ((Map<?, ?>) value).values().forEach(e -> doAddParam(statement, e)); 196 } else { 197 doAddParam(statement, value); 198 } 199 } 200 } else { 201 doAddParam(statement, object); 202 } 203 } 204 } 205 206 private void doAddParam(Statement statement, Object object) { 207 try { 208 if (object instanceof TypeHandlerObject) { 209 ((TypeHandlerObject) object).setParameter(createPreparedStatement(statement), 0); 210 } else if (object instanceof java.sql.Array) { 211 Object array = ((java.sql.Array) object).getArray(); 212 queryParams.add(array); 213 } else { 214 queryParams.add(object); 215 } 216 } catch (SQLException e) { 217 // ignore 218 } 219 } 220 221 public String getFullSql() { 222 List<Object> queryParams = getQueryParams(); 223 return SqlUtil.replaceSqlParams(getQuery(), queryParams == null ? null : queryParams.toArray()); 224 } 225 226 private PreparedStatement createPreparedStatement(Statement statement) { 227 return (PreparedStatement) Proxy.newProxyInstance( 228 AuditMessage.class.getClassLoader(), 229 new Class[]{PreparedStatement.class}, (proxy, method, args) -> { 230 if (args != null && (args.length == 2 || args.length == 3)) { 231 doAddParam(statement, args[1]); 232 } else if ("getConnection".equals(method.getName())) { 233 return statement.getConnection(); 234 } 235 return null; 236 }); 237 } 238 239 public int getQueryCount() { 240 return queryCount; 241 } 242 243 public void setQueryCount(int queryCount) { 244 this.queryCount = queryCount; 245 } 246 247 public long getQueryTime() { 248 return queryTime; 249 } 250 251 public void setQueryTime(long queryTime) { 252 this.queryTime = queryTime; 253 } 254 255 public long getElapsedTime() { 256 return elapsedTime; 257 } 258 259 public void setElapsedTime(long elapsedTime) { 260 this.elapsedTime = elapsedTime; 261 } 262 263 public Map<String, Object> getMetas() { 264 return metas; 265 } 266 267 public void setMetas(Map<String, Object> metas) { 268 this.metas = metas; 269 } 270 271 public void addMeta(String key, Object value) { 272 if (metas == null) { 273 metas = new HashMap<>(); 274 } 275 metas.put(key, value); 276 } 277 278 public String getStmtId() { 279 return stmtId; 280 } 281 282 public void setStmtId(String stmtId) { 283 this.stmtId = stmtId; 284 } 285 286 public String getDsName() { 287 return dsName; 288 } 289 290 public void setDsName(String dsName) { 291 this.dsName = dsName; 292 } 293 294 @Override 295 public String toString() { 296 return "AuditMessage{" + 297 "platform='" + platform + '\'' + 298 ", module='" + module + '\'' + 299 ", url='" + url + '\'' + 300 ", bizId='" + bizId + '\'' + 301 ", user='" + user + '\'' + 302 ", userIp='" + userIp + '\'' + 303 ", hostIp='" + hostIp + '\'' + 304 ", query='" + query + '\'' + 305 ", queryParams=" + queryParams + 306 ", queryCount=" + queryCount + 307 ", queryTime=" + queryTime + 308 ", elapsedTime=" + elapsedTime + 309 ", stmtId=" + stmtId + 310 ", dsName=" + dsName + 311 ", metas=" + metas + 312 '}'; 313 } 314 315}