前段时间调研审计日志,发现海豚调度3.0源码已经有这个功能了,测试了一下发现功能并没有完全实现,详见dolphinscheduler 3.0.1 审计日志,至于2.0的版本很早就有审计日志相关类了,只不过都是开发未完成状态。目前是参照若依管理系统的操作日志功能,把代码提取出来之后,稍作优化,本文主要记录做了哪些优化以、使用过程遇到的注意事项及相关技术点。


直接提取若依中记录操作日志的相关类,运用的AOP,切面、切点。核心类为LogAspect和Log,提取出来之后,根据报错,缺少哪个类,把相关类拷贝过来即可,我这边没有直接放到海豚调度,而是单独搞了个项目,主要为了方便其他项目也能调用。
LogAspect:切面处理类,解析请求响应参数入库等
com.ruoyi.framework.aspectj.LogAspect
切点注解接口,拎出来之后,接口名称我改成了LogAnnotation,海豚2.0自带接口为AccessLogAnnotation,只不过是个开发未完成的功能,由于这部分要做成公共的功能,所以直接放弃了海豚这部分的半成品
com.ruoyi.common.annotation.Log
表为操作日志记录表-sys_oper_log
CREATE TABLE `sys_oper_log` (`oper_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键',`title` varchar(50) DEFAULT '' COMMENT '模块标题',`business_type` int DEFAULT '0' COMMENT '业务类型(0其它 1新增 2修改 3删除)',`method` varchar(100) DEFAULT '' COMMENT '方法名称',`request_method` varchar(10) DEFAULT '' COMMENT '请求方式',`operator_type` int DEFAULT '0' COMMENT '操作类别(0其它 1后台用户 2手机端用户)',`oper_name` varchar(50) DEFAULT '' COMMENT '操作人员',`dept_name` varchar(50) DEFAULT '' COMMENT '部门名称',`oper_url` varchar(255) DEFAULT '' COMMENT '请求URL',`oper_ip` varchar(128) DEFAULT '' COMMENT '主机地址',`oper_location` varchar(255) DEFAULT '' COMMENT '操作地点',`oper_param` varchar(2000) DEFAULT '' COMMENT '请求参数',`json_result` varchar(2000) DEFAULT '' COMMENT '返回参数',`status` int DEFAULT '0' COMMENT '操作状态(0正常 1异常)',`error_msg` varchar(2000) DEFAULT '' COMMENT '错误消息',`oper_time` datetime DEFAULT NULL COMMENT '操作时间',PRIMARY KEY (`oper_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1068 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='操作日志记录';
LogAnnotation注解以工作流定义-修改为例,增加注解,原先的AccessLogAnnotation注解直接去掉了,没用,此时编辑工作流的时候,请求响应参数及方法等都会存到数据库

背景:工作流定义-更新,内部涉及三张表的操作,对应多个方法,因此想要记录所有的方法的请求响应参数
public,内部私有方法代理是获取不到的updateDagDefine,即便改为public,添加注解也不会生效
改为public,注入本身,再次调用,注解有效(纯测试,虽然spring支持循环依赖,可以自我注入,但是总感觉这样干有风险)


比如改成updateProcessDefinition这种,通过controller中注入该方法接口


背景:工作流定义-更新,内部涉及三张表的操作,对应多个方法,添加注解后全部记录了下来,但是不好区分,哪些记录是同一个操作产生的,即同一个批次,因此增加批次号-batch_no字段,更新工作流操作,底层涉及三种表的更新,这些操作都是在同一个线程,因此可以通过ThreadLocal去实现

ThreadLocal使用很简单,一个set方法,一个get方法,一个remove方法,主要风险在于内存泄漏,一般调用完get方法需要调用remove,也可以实现AutoCloseable ,自动回收,主要何时调用remove不好辨别
BatchNoUtils ,实现了AutoCloseable 接口,否则还要单独调用remove方法public class BatchNoUtils implements AutoCloseable {private static final ThreadLocal threadLocal = new ThreadLocal<>();public static void add(Long batchNo) {threadLocal.set(batchNo);}public static Long getBatchNo() {return threadLocal.get();}@Overridepublic void close() {threadLocal.remove();}
}
BatchNoFilter ,在调用方法之前设置批次号(即threadLocal.set(),初始化值,直接用的yyyyMMddHHmmssSSS)import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.copote.comb.manager.util.DateUtils;/*** 请求处理前生成批次号.** @author rxz*/
@Component
public class BatchNoFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {BatchNoUtils.add(Long.valueOf(DateUtils.dateTimeNow("yyyyMMddHHmmssSSS")));filterChain.doFilter(request, response);}
}


测试结果中,可以看到IP归属地,北京市,看了下代码,直接调用http://whois.pconline.com.cn/ipJson.jsp,联网就行,本来以为这种操作都是收费的呢,看来也有免费的接口


package com.renxiaozhao.demo;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;public class Test2 {public static void main(String[] args) {getLocation("192.168.3.10");getLocation("36.99.142.234");}private static String getLocation(String ip) {StringBuilder result = new StringBuilder();BufferedReader in = null;String url = "http://whois.pconline.com.cn/ipJson.jsp?";try {String param = "ip=" + ip + "&json=true";URL realUrl = new URL(url+param);URLConnection connection = realUrl.openConnection();connection.setRequestProperty("accept", "*/*");connection.setRequestProperty("connection", "Keep-Alive");connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");connection.connect();in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "GBK"));String line;while ((line = in.readLine()) != null) {result.append(line);}System.out.println(result);} catch (Exception e) {System.out.println("获取IP归属地异常:" + e.getMessage());} finally {try {if (in != null) {in.close();}} catch (Exception ex) {System.out.println("关闭流异常:" + ex.getMessage());}}return result.toString();}
}
上一篇:安逸生活的唯美句子
下一篇:形容本该高兴却高兴不起来的句子