feat: 增强参数校验失败的日志记录,详细输出字段和全局错误信息,优化请求对象的错误处理,提升调试和维护效率

This commit is contained in:
yahaozhang
2025-10-11 14:08:29 +08:00
parent 2056ad71b5
commit eb41a01190
2 changed files with 71 additions and 9 deletions

View File

@@ -379,7 +379,24 @@ public Mono<Boolean> deleteLink(@PathVariable("codeNo") String codeNo, Authentic
@Operation(summary = "选择区域", description = "用户选择游戏区域Q或V选区成功后生成二维码")
public Mono<SelectRegionResponse> selectRegion(@Valid @RequestBody SelectRegionRequest request) {
log.info("=== 控制器: 接收选区请求 ===");
log.info("HTTP请求参数: code={}, region={}", request.getCode(), request.getRegion());
log.info("HTTP请求参数: code=[{}], region=[{}]", request.getCode(), request.getRegion());
log.info("请求对象详情: {}", request.toString());
// 额外的参数验证日志在Spring校验之后
if (request.getCode() != null) {
log.info("code参数分析: 长度={}, 是否为空={}, 去空格后=[{}]",
request.getCode().length(), request.getCode().trim().isEmpty(), request.getCode().trim());
} else {
log.warn("code参数为null");
}
if (request.getRegion() != null) {
log.info("region参数分析: 长度={}, 值=[{}], 是否匹配Q或V={}",
request.getRegion().length(), request.getRegion(),
"Q".equals(request.getRegion()) || "V".equals(request.getRegion()));
} else {
log.warn("region参数为null");
}
return linkStatusService.selectRegion(request.getCode(), request.getRegion())
.doOnSuccess(response -> {
@@ -390,7 +407,7 @@ public Mono<Boolean> deleteLink(@PathVariable("codeNo") String codeNo, Authentic
})
.doOnError(error -> {
log.error("控制器: 选区请求处理失败");
log.error("错误详情: code={}, region={}, errorType={}, errorMessage={}",
log.error("错误详情: code=[{}], region=[{}], errorType={}, errorMessage={}",
request.getCode(), request.getRegion(), error.getClass().getSimpleName(), error.getMessage(), error);
});
}

View File

@@ -62,23 +62,68 @@ public class GlobalExceptionHandler {
@ExceptionHandler(WebExchangeBindException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Object handleBindException(WebExchangeBindException e) {
log.warn("400 ValidationError: {} - Field errors: {} - Global errors: {}",
e.getMessage(), e.getFieldErrors().size(), e.getGlobalErrors().size());
log.error("=== 参数校验失败详情 ===");
log.error("异常类型: WebExchangeBindException");
log.error("异常消息: {}", e.getMessage());
log.error("字段错误数量: {}, 全局错误数量: {}", e.getFieldErrors().size(), e.getGlobalErrors().size());
var details = new java.util.LinkedHashMap<String, Object>();
e.getFieldErrors().forEach(fe -> details.put(fe.getField(), fe.getDefaultMessage()));
e.getGlobalErrors().forEach(ge -> details.put(ge.getObjectName(), ge.getDefaultMessage()));
// 详细记录字段错误
if (!e.getFieldErrors().isEmpty()) {
log.error("--- 字段校验错误详情 ---");
e.getFieldErrors().forEach(fe -> {
log.error("字段: {}, 拒绝值: [{}], 错误消息: {}, 错误代码: {}",
fe.getField(), fe.getRejectedValue(), fe.getDefaultMessage(), fe.getCode());
details.put(fe.getField(), fe.getDefaultMessage());
});
}
// 详细记录全局错误
if (!e.getGlobalErrors().isEmpty()) {
log.error("--- 全局校验错误详情 ---");
e.getGlobalErrors().forEach(ge -> {
log.error("对象: {}, 错误消息: {}, 错误代码: {}",
ge.getObjectName(), ge.getDefaultMessage(), ge.getCode());
details.put(ge.getObjectName(), ge.getDefaultMessage());
});
}
// 记录请求的原始数据(如果可获取)
if (e.getBindingResult() != null && e.getBindingResult().getTarget() != null) {
log.error("请求对象类型: {}", e.getBindingResult().getTarget().getClass().getSimpleName());
log.error("请求对象内容: {}", e.getBindingResult().getTarget().toString());
}
log.error("=== 参数校验失败详情结束 ===");
return body(HttpStatus.BAD_REQUEST.value(), "参数校验失败", details);
}
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Object handleConstraintViolation(ConstraintViolationException e) {
log.warn("400 ConstraintViolation: {} - Violations: {}",
e.getMessage(), e.getConstraintViolations().size());
log.error("=== 约束校验失败详情 ===");
log.error("异常类型: ConstraintViolationException");
log.error("异常消息: {}", e.getMessage());
log.error("约束违反数量: {}", e.getConstraintViolations().size());
var details = new java.util.LinkedHashMap<String, Object>();
log.error("--- 约束违反详情 ---");
for (ConstraintViolation<?> v : e.getConstraintViolations()) {
details.put(String.valueOf(v.getPropertyPath()), v.getMessage());
String propertyPath = String.valueOf(v.getPropertyPath());
String message = v.getMessage();
Object invalidValue = v.getInvalidValue();
log.error("属性路径: {}, 无效值: [{}], 错误消息: {}, 约束注解: {}",
propertyPath, invalidValue, message, v.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName());
details.put(propertyPath, message);
}
log.error("=== 约束校验失败详情结束 ===");
return body(HttpStatus.BAD_REQUEST.value(), "参数校验失败", details);
}