package com.whyc.aop;/* package com.com.whyc.com.whyc.aop; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import com.com.whyc.dto.Response; import com.com.whyc.service.UserLogService; import com.com.whyc.util.JsonUtil; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; */ /** * 定义aop,对特定的接口进行内容捕捉,生成操作日志 * 切面为controller * 切点为Point表达式 * 具体连接点为JoinPoint * 处理方式为doAfterReturning * *//* @Component @Aspect public class OperationLogAspect { @Autowired private UserLogService service; */ /**定义切点*//* @Pointcut(value = "execution(public * com.com.whyc..controller.*.add*(..))" + "|| execution(public * com.com.whyc..controller.*.delete*(..))" + "|| execution(public * com.com.whyc..controller.*.update*(..))" //"|| execution(public * com.com.whyc..controller.LoginController.*(..))" LoginController模块有专门日志定义转化,不需要通用的拦截. ) private void operationLogPointcut(){}; */ /** * aop处理类,对捕捉到的切点接口,进行数据处理 * 以 文档类型管理里面的新增为例: * 请求: POST * 请求地址: /pis/docType/add * 具体代码: com.com.whyc.controller.DocTypeController.add(DocType)) * 参数: {"name":"显示屏类型"} * * 拦截得到的字段: * signature: com.com.whyc.controller.DocTypeController.add(DocType) * methodSignature: com.com.whyc.controller.DocTypeController.add(DocType) * methodName: add * fullClassName: com.com.whyc.controller.DocTypeController * classNameTrue: DocTypeController * parameterNames: 是数组,这个是代码里面传参的参数名,示例只有一个参数 docType * args: 是数组,示例只有一个参数,参数值为Oject -DocType(id=5, name=显示屏类型, updateTime=null, CreateTime=Mon Jul 07 10:39:11 CST 2025),通过toString来转化为字符串存储,需要对象有toString方法 * map: 将parameterNames和args进行对应转换,并保存为map,保存了最终的接口明细参数.docType -> {"id":5,"name":"显示屏类型","CreateTime":"Jul 7, 2025 10:39:11 AM"} * * TODO 这个输入模块需要迭代的具体工作量: * 1.将所有的Controller转化为具体操作日志模块 * 2.特定模块定义及划分日志类型 * 以上两个,在同一个Switch...Case...模块下,进行定义,并保存为枚举类,方便后续扩展,以及统一处理. * *//* @AfterReturning(pointcut = "operationLogPointcut()",returning = "resp") public void doAfterReturnOperation(JoinPoint point,Object resp){ Response response = (Response) resp; Signature signature = point.getSignature(); String methodSignature = signature.toString(); //方法名 // e.g:update String methodName = signature.getName(); //执行的类全名 // e.g: com.com.whyc.controller.CKPowerDevRtSetController String fullClassName = signature.getDeclaringTypeName(); //获取类型 String[] fullClassNameSplit = fullClassName.split("\\."); //类名 // e.g: CKPowerDevRtSetController String classNameTrue = fullClassNameSplit[fullClassNameSplit.length - 1]; Integer category = 0; Integer type = 0; String operationTypeName = ""; //TODO 下面这段将优化,采用switch case 代替if else,提高代码可读性和优化性能 //系统级 */ /*if (classNameTrue.equals("UserInfController")) { if(methodName.contains("add")){ //用户新增 category = OperationLogEnum.TYPE_1_SYS.getType(); type = OperationLogEnum.TYPE_2_USER_ADD.getType(); operationTypeName = OperationLogEnum.TYPE_2_USER_ADD.getName(); }else if(methodName.contains("update")){ //用户修改 category = OperationLogEnum.TYPE_1_SYS.getType(); type = OperationLogEnum.TYPE_2_USER_UPDATE.getType(); operationTypeName = OperationLogEnum.TYPE_2_USER_UPDATE.getName(); }else if(methodName.contains("delete")){ //用户删除 category = OperationLogEnum.TYPE_1_SYS.getType(); type = OperationLogEnum.TYPE_2_USER_DELETE.getType(); operationTypeName = OperationLogEnum.TYPE_2_USER_DELETE.getName(); }else if(methodName.contains("resetSnId")){ //密码重置 category = OperationLogEnum.TYPE_1_SYS.getType(); type = OperationLogEnum.TYPE_2_USER_UPDATE_PASSWORD.getType(); operationTypeName = OperationLogEnum.TYPE_2_USER_UPDATE_PASSWORD.getName(); } }else if(classNameTrue.equals("LoginController")){ if(methodName.equals("login")){ if((boolean) response.getData()){ //用户登录 category = OperationLogEnum.TYPE_1_SYS.getType(); type = OperationLogEnum.TYPE_2_LOGIN.getType(); operationTypeName = OperationLogEnum.TYPE_2_LOGIN.getName(); }else { //用户登录失败 category = OperationLogEnum.TYPE_1_SYS.getType(); type = OperationLogEnum.TYPE_2_LOGIN_FAIL.getType(); operationTypeName = OperationLogEnum.TYPE_2_LOGIN_FAIL.getName(); } } else if(methodName.equals("logout")){ //用户退出 category = OperationLogEnum.TYPE_1_SYS.getType(); type = OperationLogEnum.TYPE_2_LOGOUT.getType(); operationTypeName = OperationLogEnum.TYPE_2_LOGOUT.getName(); } else if(methodName.equals("changeSnId")){ //用户密码重置 category = OperationLogEnum.TYPE_1_SYS.getType(); type = OperationLogEnum.TYPE_2_USER_UPDATE_PASSWORD.getType(); operationTypeName = OperationLogEnum.TYPE_2_USER_UPDATE_PASSWORD.getName(); } }else if(classNameTrue.contains("Alarm") ||classNameTrue.contains("Alm")){ //告警设置 if(methodName.startsWith("update")){ category = OperationLogEnum.TYPE_1_SERVICE.getType(); type = OperationLogEnum.TYPE_2_ALARM.getType(); operationTypeName = OperationLogEnum.TYPE_2_ALARM.getName(); } }else if(classNameTrue.contains("plan")){ if(methodName.startsWith("static")){//统计计划 category = OperationLogEnum.TYPE_1_SERVICE.getType(); type = OperationLogEnum.TYPE_2_PLAN_MON.getType(); operationTypeName = OperationLogEnum.TYPE_2_PLAN_MON.getName(); } }*//* String module = "模块"; String className = classNameTrue.replace("Controller", module); */ /* //操作时间 Date operationTime = new Date(); //客户端ip HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); String terminalIp = request.getRemoteAddr();*//* //操作信息 //获取切点方法信息 String[] parameterNames = ((MethodSignature) signature).getParameterNames(); Object[] args = point.getArgs(); HashMap map = new HashMap<>(); for (int i = 0; i < parameterNames.length; i++) { if (args[i] != null) { StringBuilder paramBuilder = new StringBuilder(); //String param = args[i].toString(); try { JsonObject paramJsonObject = JsonUtil.getGson().toJsonTree(args[i]).getAsJsonObject(); //TODO 如存在需要忽略的参数,这里进行处理 */ /*if(paramJsonObject.has("logList")){ paramJsonObject.remove("logList"); JsonElement jsonElement = new JsonPrimitive("logList字段忽略存储"); paramJsonObject.add("logList",jsonElement); }*//* paramBuilder.append(paramJsonObject.toString()); }catch (Exception e){ paramBuilder.append(args[i].toString()); } map.put(parameterNames[i], paramBuilder.toString()); } } //登录接口的密码,不存储 if (methodSignature.contains("LoginController.login")) { map.put("password","密码密文保密,忽略存储"); } //TODO 修改密码接口的密码,也不存储 */ /*else if(methodSignature.contains("LoginController.changeSnId")){ map.put("oldSnId","旧密码密文保密,忽略存储"); map.put("newSnId","新密码密文保密,忽略存储"); }*//* //规范示例: 执行的文档类型管理的添加操作. String message = "执行了" + className + "的" + operationTypeName + "操作."; //规范示例:具体调用方法为: DocTypeController.add,具体参数为:{docType={"id":4,"name":"显示屏类型","CreateTime":"Jul 7, 2025 10:16:18 AM"}} String messageDetail = "具体调用方法为:" + classNameTrue+"."+methodName + ",具体参数为:" + map.toString(); service.add(category, type, message, messageDetail); } } */