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 * 数据库名称。 100 */ 101 private String dsName; 102 103 /** 104 * 其他扩展元信息。 105 */ 106 private Map<String, Object> metas; 107 108 public String getPlatform() { 109 return platform; 110 } 111 112 public void setPlatform(String platform) { 113 this.platform = platform; 114 } 115 116 public String getModule() { 117 return module; 118 } 119 120 public void setModule(String module) { 121 this.module = module; 122 } 123 124 public String getUrl() { 125 return url; 126 } 127 128 public void setUrl(String url) { 129 this.url = url; 130 } 131 132 public String getBizId() { 133 return bizId; 134 } 135 136 public void setBizId(String bizId) { 137 this.bizId = bizId; 138 } 139 140 public String getUser() { 141 return user; 142 } 143 144 public void setUser(String user) { 145 this.user = user; 146 } 147 148 public String getUserIp() { 149 return userIp; 150 } 151 152 public void setUserIp(String userIp) { 153 this.userIp = userIp; 154 } 155 156 public String getHostIp() { 157 return hostIp; 158 } 159 160 public void setHostIp(String hostIp) { 161 this.hostIp = hostIp; 162 } 163 164 public String getQuery() { 165 return query; 166 } 167 168 public void setQuery(String query) { 169 this.query = query; 170 } 171 172 public List<Object> getQueryParams() { 173 return queryParams; 174 } 175 176 public void setQueryParams(List<Object> queryParams) { 177 this.queryParams = queryParams; 178 } 179 180 public void addParams(Statement statement, Object... objects) { 181 if (queryParams == null) { 182 queryParams = new ArrayList<>(); 183 } 184 185 for (Object object : objects) { 186 if (object != null && ClassUtil.isArray(object.getClass())) { 187 for (int i = 0; i < Array.getLength(object); i++) { 188 Object value = Array.get(object, i); 189 if (value instanceof Map) { 190 ((Map<?, ?>) value).values().forEach(e -> doAddParam(statement, e)); 191 } else { 192 doAddParam(statement, value); 193 } 194 } 195 } else { 196 doAddParam(statement, object); 197 } 198 } 199 } 200 201 private void doAddParam(Statement statement, Object object) { 202 try { 203 if (object instanceof TypeHandlerObject) { 204 ((TypeHandlerObject) object).setParameter(createPreparedStatement(statement), 0); 205 } else if (object instanceof java.sql.Array) { 206 Object array = ((java.sql.Array) object).getArray(); 207 queryParams.add(array); 208 } else { 209 queryParams.add(object); 210 } 211 } catch (SQLException e) { 212 // ignore 213 } 214 } 215 216 public String getFullSql() { 217 List<Object> queryParams = getQueryParams(); 218 return SqlUtil.replaceSqlParams(getQuery(), queryParams == null ? null : queryParams.toArray()); 219 } 220 221 private PreparedStatement createPreparedStatement(Statement statement) { 222 return (PreparedStatement) Proxy.newProxyInstance( 223 AuditMessage.class.getClassLoader(), 224 new Class[]{PreparedStatement.class}, (proxy, method, args) -> { 225 if (args != null && (args.length == 2 || args.length == 3)) { 226 doAddParam(statement, args[1]); 227 } else if ("getConnection".equals(method.getName())) { 228 return statement.getConnection(); 229 } 230 return null; 231 }); 232 } 233 234 public int getQueryCount() { 235 return queryCount; 236 } 237 238 public void setQueryCount(int queryCount) { 239 this.queryCount = queryCount; 240 } 241 242 public long getQueryTime() { 243 return queryTime; 244 } 245 246 public void setQueryTime(long queryTime) { 247 this.queryTime = queryTime; 248 } 249 250 public long getElapsedTime() { 251 return elapsedTime; 252 } 253 254 public void setElapsedTime(long elapsedTime) { 255 this.elapsedTime = elapsedTime; 256 } 257 258 public Map<String, Object> getMetas() { 259 return metas; 260 } 261 262 public void setMetas(Map<String, Object> metas) { 263 this.metas = metas; 264 } 265 266 public void addMeta(String key, Object value) { 267 if (metas == null) { 268 metas = new HashMap<>(); 269 } 270 metas.put(key, value); 271 } 272 273 public String getDsName() { 274 return dsName; 275 } 276 277 public void setDsName(String dsName) { 278 this.dsName = dsName; 279 } 280 281 @Override 282 public String toString() { 283 return "AuditMessage{" + 284 "platform='" + platform + '\'' + 285 ", module='" + module + '\'' + 286 ", url='" + url + '\'' + 287 ", bizId='" + bizId + '\'' + 288 ", user='" + user + '\'' + 289 ", userIp='" + userIp + '\'' + 290 ", hostIp='" + hostIp + '\'' + 291 ", query='" + query + '\'' + 292 ", queryParams=" + queryParams + 293 ", queryCount=" + queryCount + 294 ", queryTime=" + queryTime + 295 ", elapsedTime=" + elapsedTime + 296 ", dsName=" + dsName + 297 ", metas=" + metas + 298 '}'; 299 } 300 301}