From db0d5e1a2d90796ba1b9be4d6871e543816d5d1b Mon Sep 17 00:00:00 2001 From: chenxing Date: Thu, 20 Aug 2026 10:57:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=A8=E9=80=81=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunhai/userbase/aspect/OapiLogAspect.java | 42 ++++++++++++++++++- .../common/GlobalExceptionHandler.java | 14 +++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/yunhai/userbase/aspect/OapiLogAspect.java b/src/main/java/com/yunhai/userbase/aspect/OapiLogAspect.java index 965e96e..c204f7b 100644 --- a/src/main/java/com/yunhai/userbase/aspect/OapiLogAspect.java +++ b/src/main/java/com/yunhai/userbase/aspect/OapiLogAspect.java @@ -1,7 +1,9 @@ package com.yunhai.userbase.aspect; -import com.alibaba.fastjson.JSON; +import com.yunhai.platform.apistd.ApiResponse; +import com.yunhai.platform.apistd.BizException; import com.yunhai.platform.appauth.AppAuthFilter; +import com.yunhai.platform.utils.exception.DException; import com.yunhai.userbase.common.annotation.OapiLog; import com.yunhai.userbase.entity.ApplicationInfo; import com.yunhai.userbase.entity.SysOapiLog; @@ -90,6 +92,8 @@ public class OapiLogAspect { } catch (Throwable e) { entity.setStatusCode(500); entity.setErrorMsg(truncate(e.getMessage(), 2000)); + // 业务异常(DException/BizException)同样构造实际返回的响应体落库,便于详情下载 + fillErrorResponse(entity, e, saveResponse, maxResponseSize); throw e; } finally { entity.setCostTime(System.currentTimeMillis() - start); @@ -213,8 +217,42 @@ public class OapiLogAspect { if (!saveResponse || result == null) { return; } + writeResponseData(entity, result, maxResponseSize); + } + + /** + * 异常路径:与 {@code GlobalExceptionHandler} 保持一致的响应体(DException/BizException → ApiResponse), + * 使日志下载内容等于调用方实际收到的 body;其余异常不构造(响应不可预期)。 + */ + private void fillErrorResponse(SysOapiLog entity, Throwable e, boolean saveResponse, int maxResponseSize) { + if (!saveResponse) { + return; + } + ApiResponse response = toApiResponse(e); + if (response == null) { + return; + } + writeResponseData(entity, response, maxResponseSize); + } + + private ApiResponse toApiResponse(Throwable e) { + if (e instanceof DException) { + DException de = (DException) e; + return ApiResponse.fail(de.getCode(), de.getMessage(), de.getData()); + } + if (e instanceof BizException) { + BizException be = (BizException) e; + return ApiResponse.fail(be.getErrorCode(), be.getMessage()); + } + return null; + } + + private void writeResponseData(SysOapiLog entity, Object payload, int maxResponseSize) { + if (payload == null) { + return; + } try { - String resp = SensitiveDataMasker.maskObject(result); + String resp = SensitiveDataMasker.maskObject(payload); if (resp == null) { return; } diff --git a/src/main/java/com/yunhai/userbase/common/GlobalExceptionHandler.java b/src/main/java/com/yunhai/userbase/common/GlobalExceptionHandler.java index 32b2632..2e740f9 100644 --- a/src/main/java/com/yunhai/userbase/common/GlobalExceptionHandler.java +++ b/src/main/java/com/yunhai/userbase/common/GlobalExceptionHandler.java @@ -5,8 +5,10 @@ import org.springframework.core.annotation.Order; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; @@ -52,6 +54,18 @@ public class GlobalExceptionHandler { return paramError(msg); } + /** 缺少必需的请求参数(@RequestParam 必填项未传,如 oapi 调用方漏传 groupId)。 */ + @ExceptionHandler(MissingServletRequestParameterException.class) + public Map handleMissingParam(MissingServletRequestParameterException ex) { + return paramError("缺少必需的请求参数: " + ex.getParameterName()); + } + + /** 请求参数类型不匹配(如 Integer 参数收到非数字字符串)。 */ + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + public Map handleTypeMismatch(MethodArgumentTypeMismatchException ex) { + return paramError("参数类型不匹配: " + ex.getName()); + } + private String fieldErrorsMessage(java.util.List fieldErrors) { if (fieldErrors == null || fieldErrors.isEmpty()) { return "参数校验失败";