使用的是mybatis-flex官网自带的sql审计功能
首先展示下 记录日志的表及实体类
/**
* 所有的sql操作记录 实体类。
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LogSqlAudit implements Serializable {
/**
* 编号
*/
@Id(keyType = KeyType.Auto)
private Long id;
/**
* sql语句
*/
private String sqlText;
/**
* 访问人
*/
private String userId;
/**
* 访问IP
*/
private String userIp;
/**
* 耗时
*/
private Long exeTime;
/**
* 访问地址
*/
private String url;
/**
* 执行时间
*/
private Date createDate;
}
测试的接口
@RestController
@RequiredArgsConstructor
@RequestMapping("log")
public class LogController {
private final LogSqlAuditService logSqlAuditService;
private final LogSqlErrorService logSqlErrorService;
@PostMapping("savaLog")
public BaseResponse<LogSqlAudit> save(@RequestBody LogSqlAudit logSqlAudit){
boolean save = logSqlAuditService.save(logSqlAudit);
if(!save){
return ResultUtils.error(ErrorCode.NULL_ERROR);
}
return ResultUtils.success(logSqlAudit);
}
@PostMapping("getLogFx")
public BaseResponse<List<LogSqlError>> getLog(){
List<LogSqlError> list = logSqlErrorService.list();
return ResultUtils.success(list);
}
}
拦截器中配置放行的接口,让这个接口可以随便访问次数。不会触发禁用该用户访问接口限流的限制。无限访问。
以上改完,接下来才是正题。
MyMessageFactory 每次访问接口就会进来执行代码
@Component
@RequiredArgsConstructor
public class MyMessageFactory implements MessageFactory {
//private final RegUtil regUtil;//目前先注释,之后加入获取用户信息方法在放开
private final HttpServletRequest request;
@Override
public AuditMessage create() {
AuditMessage message = new AuditMessage();
// 在这里
// 设置 message 的基础内容,包括 platform、module、url、user、userIp、hostIp 内容
// 剩下的 query、queryParams、queryCount、queryTime、elapsedTime 为 mybatis-flex 设置
message.setPlatform("IPRMIS2.0");
message.setUser("admin");//暂时写固定 之后有jwt或者redis存登录人的时候,再去改
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if("0:0:0:0:0:0:0:1".equals(ip)){//本地运行会出现这个情况,如果部署到公网上就不会是0:0:0:0:0:0:0:1 会显示本机公网的ip 这里就是本地电脑先写本地
ip = "127.0.0.1";
}
message.setUserIp(ip);
message.setUrl(request.getRequestURI());
return message;
}
}
MyMessageReporter 记录一段时间的接口才会触发sendMessages
@Slf4j
@Component
public class MyMessageReporter implements MessageReporter {
@Override
public void sendMessages(List<AuditMessage> messages) {
messages.forEach(m -> {
System.out.println(">>>>>>Sql Audit: " + m.toString());
if(m.getQuery().contains("log_sql_audit")){//这是记录日志的表 这里就不用存日志记录表了,排除
return;
}
try {
//1, 得到URL对象
URL url = new URL("http://10.11.6.88:9001/log/savaLog");
//2, 打开连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//3, 设置提交类型
conn.setRequestMethod("POST");
conn.setRequestProperty("content-Type", "application/json; charset=utf-8");
//4, 设置允许写出数据,默认是不允许 false
conn.setDoOutput(true);
conn.setDoInput(true);//当前的连接可以从服务器读取内容, 默认是true
//5, 获取向服务器写出数据的流
OutputStream os = conn.getOutputStream();
String sqlText = m.getQuery();
LogSqlAudit logSqlAudit = new LogSqlAudit();
logSqlAudit.setSqlText(sqlText);
logSqlAudit.setCreateDate(new Date());
logSqlAudit.setUrl(m.getUrl());
logSqlAudit.setExeTime(m.getElapsedTime());
String ip = m.getUserIp();
if ("0:0:0:0:0:0:0:1".equals(ip)) {//本地运行会出现这个情况,如果部署到公网上就不会是0:0:0:0:0:0:0:1 会显示本机公网的ip 这里就是本地电脑先写本地
ip = "127.0.0.1";
}
logSqlAudit.setUserIp(ip);
logSqlAudit.setUserId(m.getUser());
ObjectMapper objectMapper = new ObjectMapper();
String jsonlog = objectMapper.writeValueAsString(logSqlAudit);//实体类转成json
//参数是键值队 , 不以"?"开始
os.write(jsonlog.getBytes());
os.flush();
//6, 获取响应的数据
//得到服务器写回的响应数据
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String str = br.readLine();
JSONObject json = JSONObject.parseObject(str);
System.out.println("响应内容为: " + json);
}catch(Exception e){
throw new BusinessException("sql审计存入数据失败",500,"");
}
});
}
}
MyAuditConfiguration配置
@Configuration
@RequiredArgsConstructor
public class MyAuditConfiguration implements MyBatisFlexCustomizer {
private final MyMessageFactory myMessageFactory;
@SneakyThrows
@Override
public void customize(FlexGlobalConfig flexGlobalConfig) {
// 开启 SQL 审计
AuditManager.setAuditEnable(true);
//设置
AuditManager.setMessageFactory(myMessageFactory);
AuditManager.setMessageReporter(new MyMessageReporter());
}
}
然后调用任意接口,看一下效果吧
成功记录!