运维页面
This commit is contained in:
@@ -6,6 +6,7 @@ import com.yunhai.bschclassmanage.entity.SyncLog;
|
||||
import com.yunhai.bschclassmanage.model.vo.PageVO;
|
||||
import com.yunhai.bschclassmanage.service.ISyncLogService;
|
||||
import com.yunhai.bschclassmanage.utils.ReflectRetryUtil;
|
||||
import com.yunhai.bschclassmanage.utils.SyncLogRetryContext;
|
||||
import com.yunhai.platform.utils.exception.DException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -23,6 +24,7 @@ import javax.persistence.criteria.Predicate;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -104,6 +106,10 @@ public class SyncLogServiceImpl implements ISyncLogService {
|
||||
if (StringUtils.isBlank(e.getClassMethod())) throw new DException("该日志缺少调用信息(classMethod),无法重试");
|
||||
if (StringUtils.isBlank(e.getJsonData())) throw new DException("该日志缺少入参(jsonData),无法重试");
|
||||
|
||||
// 记录本次重试元数据(重试次数 +1、重试时间)
|
||||
e.setRetryCount((e.getRetryCount() == null ? 0 : e.getRetryCount()) + 1);
|
||||
e.setLastRetryTime(LocalDateTime.now());
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> argMap = JSON.parseObject(e.getJsonData(), LinkedHashMap.class);
|
||||
@@ -133,11 +139,26 @@ public class SyncLogServiceImpl implements ISyncLogService {
|
||||
}
|
||||
|
||||
Method invokeMethod = ReflectRetryUtil.getInvokeMethod(resolved.bean, target);
|
||||
return invokeMethod.invoke(resolved.bean, args);
|
||||
SyncLogRetryContext.mark(); // 标记为重试,切面生成新日志时在同步类型名追加"(重试)"
|
||||
Object result = invokeMethod.invoke(resolved.bean, args);
|
||||
e.setLastRetryStatus(1); // 本次重试成功
|
||||
return result;
|
||||
} catch (DException de) {
|
||||
e.setLastRetryStatus(0); // 本次重试失败
|
||||
throw de;
|
||||
} catch (InvocationTargetException | IllegalAccessException ex) {
|
||||
e.setLastRetryStatus(0); // 本次重试失败
|
||||
throw ReflectRetryUtil.rethrow(ex);
|
||||
} catch (RuntimeException re) {
|
||||
e.setLastRetryStatus(0); // 本次重试失败(入参转换 / 定位等)
|
||||
throw re;
|
||||
} finally {
|
||||
SyncLogRetryContext.clear(); // 清除重试标记,避免线程池复用泄漏
|
||||
try {
|
||||
repository.save(e); // 同步落库重试元数据(次数 / 上次状态 / 时间)
|
||||
} catch (Exception saveEx) {
|
||||
log.error("重试元数据落库失败, id={}", e.getId(), saveEx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+45
-24
@@ -7,6 +7,7 @@ import com.yunhai.bschclassmanage.model.vo.PageVO;
|
||||
import com.yunhai.bschclassmanage.service.ISysOperationLogService;
|
||||
import com.yunhai.bschclassmanage.utils.GzipUtil;
|
||||
import com.yunhai.bschclassmanage.utils.ReflectRetryUtil;
|
||||
import com.yunhai.bschclassmanage.utils.SyncLogRetryContext;
|
||||
import com.yunhai.bschclassmanage.utils.UserContext;
|
||||
import com.yunhai.platform.utils.exception.DException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -139,43 +140,63 @@ public class SysOperationLogServiceImpl implements ISysOperationLogService {
|
||||
throw new DException("非 JSON 数组入参(如 GET query)无法可靠重放,请手动重试");
|
||||
}
|
||||
|
||||
JSONArray arr;
|
||||
try {
|
||||
arr = JSONArray.parseArray(e.getRequestParams());
|
||||
} catch (Exception ex) {
|
||||
throw new DException("入参解析失败(requestParams),无法重试");
|
||||
}
|
||||
if (arr == null) throw new DException("入参解析失败(requestParams),无法重试");
|
||||
|
||||
ReflectRetryUtil.Resolved resolved = ReflectRetryUtil.resolveBeanAndMethod(
|
||||
applicationContext, e.getClassMethod(), arr.size());
|
||||
|
||||
Method target = resolved.method;
|
||||
Parameter[] params = target.getParameters();
|
||||
Object[] args = new Object[params.length];
|
||||
int jsonIdx = 0;
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (ReflectRetryUtil.isSkippable(params[i].getType())) {
|
||||
args[i] = null; // 容器注入参数,无法重建
|
||||
} else {
|
||||
Object raw = (jsonIdx < arr.size()) ? arr.get(jsonIdx++) : null;
|
||||
args[i] = ReflectRetryUtil.convert(raw, params[i]);
|
||||
}
|
||||
}
|
||||
// 记录本次重试元数据(重试次数 +1、重试时间)
|
||||
e.setRetryCount((e.getRetryCount() == null ? 0 : e.getRetryCount()) + 1);
|
||||
e.setLastRetryTime(LocalDateTime.now());
|
||||
|
||||
// 还原原操作人上下文,使重放触发的审计切面记录正确操作人;结束后恢复本次请求上下文
|
||||
UserContext.UserInfo snapshot = UserContext.getCurrentUser();
|
||||
try {
|
||||
JSONArray arr;
|
||||
try {
|
||||
arr = JSONArray.parseArray(e.getRequestParams());
|
||||
} catch (Exception ex) {
|
||||
throw new DException("入参解析失败(requestParams),无法重试");
|
||||
}
|
||||
if (arr == null) throw new DException("入参解析失败(requestParams),无法重试");
|
||||
|
||||
ReflectRetryUtil.Resolved resolved = ReflectRetryUtil.resolveBeanAndMethod(
|
||||
applicationContext, e.getClassMethod(), arr.size());
|
||||
|
||||
Method target = resolved.method;
|
||||
Parameter[] params = target.getParameters();
|
||||
Object[] args = new Object[params.length];
|
||||
int jsonIdx = 0;
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (ReflectRetryUtil.isSkippable(params[i].getType())) {
|
||||
args[i] = null; // 容器注入参数,无法重建
|
||||
} else {
|
||||
Object raw = (jsonIdx < arr.size()) ? arr.get(jsonIdx++) : null;
|
||||
args[i] = ReflectRetryUtil.convert(raw, params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
UserContext.setUserId(e.getUserId());
|
||||
UserContext.setUserName(e.getUserName());
|
||||
UserContext.setSchId(e.getSchId());
|
||||
UserContext.setIp(e.getRequestIp());
|
||||
Method invokeMethod = ReflectRetryUtil.getInvokeMethod(resolved.bean, target);
|
||||
return invokeMethod.invoke(resolved.bean, args);
|
||||
SyncLogRetryContext.mark(); // 标记为重试,审计切面生成新日志时在操作类型追加"(重试)"
|
||||
Object result = invokeMethod.invoke(resolved.bean, args);
|
||||
e.setLastRetryStatus(1); // 本次重试成功
|
||||
return result;
|
||||
} catch (DException de) {
|
||||
e.setLastRetryStatus(0); // 本次重试失败
|
||||
throw de;
|
||||
} catch (InvocationTargetException | IllegalAccessException ex) {
|
||||
e.setLastRetryStatus(0); // 本次重试失败
|
||||
throw ReflectRetryUtil.rethrow(ex);
|
||||
} catch (RuntimeException re) {
|
||||
e.setLastRetryStatus(0); // 本次重试失败(入参转换 / 定位等)
|
||||
throw re;
|
||||
} finally {
|
||||
UserContext.setUserInfo(snapshot);
|
||||
SyncLogRetryContext.clear(); // 清除重试标记,避免线程池复用泄漏
|
||||
try {
|
||||
repository.save(e); // 同步落库重试元数据(次数 / 上次状态 / 时间)
|
||||
} catch (Exception saveEx) {
|
||||
log.error("审计日志重试元数据落库失败, id={}", e.getId(), saveEx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user