From eb41a01190014048c162ee5a84f4bcf018636345 Mon Sep 17 00:00:00 2001 From: yahaozhang Date: Sat, 11 Oct 2025 14:08:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BA=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=A4=B1=E8=B4=A5=E7=9A=84=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=EF=BC=8C=E8=AF=A6=E7=BB=86=E8=BE=93=E5=87=BA?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=92=8C=E5=85=A8=E5=B1=80=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=EF=BC=8C=E4=BC=98=E5=8C=96=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E7=9A=84=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E6=8F=90=E5=8D=87=E8=B0=83=E8=AF=95=E5=92=8C=E7=BB=B4?= =?UTF-8?q?=E6=8A=A4=E6=95=88=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/link/LinkController.java | 21 ++++++- .../exception/GlobalExceptionHandler.java | 59 ++++++++++++++++--- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/gameplatform/server/controller/link/LinkController.java b/src/main/java/com/gameplatform/server/controller/link/LinkController.java index 0e611b6..01a8dcd 100644 --- a/src/main/java/com/gameplatform/server/controller/link/LinkController.java +++ b/src/main/java/com/gameplatform/server/controller/link/LinkController.java @@ -379,7 +379,24 @@ public Mono deleteLink(@PathVariable("codeNo") String codeNo, Authentic @Operation(summary = "选择区域", description = "用户选择游戏区域(Q或V),选区成功后生成二维码") public Mono 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 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); }); } diff --git a/src/main/java/com/gameplatform/server/exception/GlobalExceptionHandler.java b/src/main/java/com/gameplatform/server/exception/GlobalExceptionHandler.java index 4bdf650..e877128 100644 --- a/src/main/java/com/gameplatform/server/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/gameplatform/server/exception/GlobalExceptionHandler.java @@ -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(); - 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(); + + 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); }