From bd0f42f80bff7877101f4a26b56e3dfb63ede966 Mon Sep 17 00:00:00 2001 From: haoxr <1490493387@qq.com> Date: Mon, 16 Dec 2024 17:08:02 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=A0=B9=E6=8D=AE=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E5=BC=80=E5=8F=91=E8=A7=84=E8=8C=83=E6=89=8B=E5=86=8C?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=92=8C=E8=B0=83=E6=95=B4=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 104 ++++++-- .../com/youlai/boot/common/result/Result.java | 4 +- .../youlai/boot/common/result/ResultCode.java | 250 +++++++++++++++--- .../boot/common/util/ResponseUtils.java | 4 +- .../com/youlai/boot/config/MybatisConfig.java | 2 +- .../youlai/boot/config/RedisCacheConfig.java | 2 +- .../com/youlai/boot/config/RedisConfig.java | 2 +- .../boot/core/aspect/RepeatSubmitAspect.java | 2 +- .../boot/core/filter/RateLimiterFilter.java | 2 +- .../filter/CaptchaValidationFilter.java | 4 +- .../security/filter/JwtValidationFilter.java | 4 +- 11 files changed, 299 insertions(+), 81 deletions(-) diff --git a/src/main/java/com/youlai/boot/common/exception/GlobalExceptionHandler.java b/src/main/java/com/youlai/boot/common/exception/GlobalExceptionHandler.java index 513aec40..2021dbd9 100644 --- a/src/main/java/com/youlai/boot/common/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/youlai/boot/common/exception/GlobalExceptionHandler.java @@ -30,85 +30,97 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; + /** * 全局系统异常处理器 *

* 调整异常处理的HTTP状态码,丰富异常处理类型 - * - * @author Gadfly - * @since 2020-02-25 13:54 - **/ + */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { + /** + * 处理绑定异常 + *

+ * 当请求参数绑定到对象时发生错误,会抛出 BindException 异常。 + */ @ExceptionHandler(BindException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(BindException e) { log.error("BindException:{}", e.getMessage()); String msg = e.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";")); - return Result.failed(ResultCode.PARAM_ERROR, msg); + return Result.failed(ResultCode.USER_REQUEST_PARAMETER_ERROR, msg); } /** - * RequestParam参数的校验 - * - * @param e - * @param - * @return + * 处理 @RequestParam 参数校验异常 + *

+ * 当请求参数在校验过程中发生违反约束条件的异常时(如 @RequestParam 验证不通过), + * 会捕获到 ConstraintViolationException 异常。 */ @ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(ConstraintViolationException e) { log.error("ConstraintViolationException:{}", e.getMessage()); String msg = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";")); - return Result.failed(ResultCode.PARAM_ERROR, msg); + return Result.failed(ResultCode.INVALID_USER_INPUT, msg); } /** - * RequestBody参数的校验 - * - * @param e - * @param - * @return + * 处理方法参数校验异常 + *

+ * 当使用 @Valid 或 @Validated 注解对方法参数进行验证时,如果验证失败, + * 会抛出 MethodArgumentNotValidException 异常。 */ @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(MethodArgumentNotValidException e) { log.error("MethodArgumentNotValidException:{}", e.getMessage()); String msg = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";")); - return Result.failed(ResultCode.PARAM_ERROR, msg); + return Result.failed(ResultCode.INVALID_USER_INPUT, msg); } + /** + * 处理接口不存在的异常 + *

+ * 当客户端请求一个不存在的路径时,会抛出 NoHandlerFoundException 异常。 + */ @ExceptionHandler(NoHandlerFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public Result processException(NoHandlerFoundException e) { log.error(e.getMessage(), e); - return Result.failed(ResultCode.RESOURCE_NOT_FOUND); + return Result.failed(ResultCode.INTERFACE_NOT_EXIST); } /** - * MissingServletRequestParameterException + * 处理缺少请求参数的异常 + *

+ * 当请求缺少必需的参数时,会抛出 MissingServletRequestParameterException 异常。 */ @ExceptionHandler(MissingServletRequestParameterException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(MissingServletRequestParameterException e) { log.error(e.getMessage(), e); - return Result.failed(ResultCode.PARAM_IS_NULL); + return Result.failed(ResultCode.REQUEST_REQUIRED_PARAMETER_IS_EMPTY); } /** - * MethodArgumentTypeMismatchException + * 处理方法参数类型不匹配的异常 + *

+ * 当请求参数类型不匹配时,会抛出 MethodArgumentTypeMismatchException 异常。 */ @ExceptionHandler(MethodArgumentTypeMismatchException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(MethodArgumentTypeMismatchException e) { log.error(e.getMessage(), e); - return Result.failed(ResultCode.PARAM_ERROR, "类型错误"); + return Result.failed(ResultCode.PARAMETER_FORMAT_MISMATCH, "类型错误"); } /** - * ServletException + * 处理 Servlet 异常 + *

+ * 当 Servlet 处理请求时发生异常时,会抛出 ServletException 异常。 */ @ExceptionHandler(ServletException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @@ -117,6 +129,11 @@ public class GlobalExceptionHandler { return Result.failed(e.getMessage()); } + /** + * 处理非法参数异常 + *

+ * 当方法接收到非法参数时,会抛出 IllegalArgumentException 异常。 + */ @ExceptionHandler(IllegalArgumentException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result handleIllegalArgumentException(IllegalArgumentException e) { @@ -124,6 +141,11 @@ public class GlobalExceptionHandler { return Result.failed(e.getMessage()); } + /** + * 处理 JSON 处理异常 + *

+ * 当处理 JSON 数据时发生错误,会抛出 JsonProcessingException 异常。 + */ @ExceptionHandler(JsonProcessingException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result handleJsonProcessingException(JsonProcessingException e) { @@ -132,7 +154,9 @@ public class GlobalExceptionHandler { } /** - * HttpMessageNotReadableException + * 处理请求体不可读的异常 + *

+ * 当请求体不可读时,会抛出 HttpMessageNotReadableException 异常。 */ @ExceptionHandler(HttpMessageNotReadableException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @@ -146,6 +170,11 @@ public class GlobalExceptionHandler { return Result.failed(errorMessage); } + /** + * 处理类型不匹配异常 + *

+ * 当方法参数类型不匹配时,会抛出 TypeMismatchException 异常。 + */ @ExceptionHandler(TypeMismatchException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result processException(TypeMismatchException e) { @@ -153,18 +182,28 @@ public class GlobalExceptionHandler { return Result.failed(e.getMessage()); } + /** + * 处理 SQL 语法错误异常 + *

+ * 当 SQL 语法错误时,会抛出 BadSqlGrammarException 异常。 + */ @ExceptionHandler(BadSqlGrammarException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public Result handleBadSqlGrammarException(BadSqlGrammarException e) { log.error(e.getMessage(), e); String errorMsg = e.getMessage(); if (StrUtil.isNotBlank(errorMsg) && errorMsg.contains("denied to user")) { - return Result.failed(ResultCode.FORBIDDEN_OPERATION); + return Result.failed(ResultCode.ACCESS_UNAUTHORIZED); } else { return Result.failed(e.getMessage()); } } + /** + * 处理 SQL 语法错误异常 + *

+ * 当 SQL 语法错误时,会抛出 SQLSyntaxErrorException 异常。 + */ @ExceptionHandler(SQLSyntaxErrorException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public Result processSQLSyntaxErrorException(SQLSyntaxErrorException e) { @@ -172,7 +211,11 @@ public class GlobalExceptionHandler { return Result.failed(e.getMessage()); } - + /** + * 处理业务异常 + *

+ * 当业务逻辑发生错误时,会抛出 BusinessException 异常。 + */ @ExceptionHandler(BusinessException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Result handleBizException(BusinessException e) { @@ -183,9 +226,14 @@ public class GlobalExceptionHandler { return Result.failed(e.getMessage()); } + /** + * 处理所有未捕获的异常 + *

+ * 当发生未捕获的异常时,会抛出 Exception 异常。 + */ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleException(Exception e) throws Exception{ + public Result handleException(Exception e) throws Exception { // 将 Spring Security 异常继续抛出,以便交给自定义处理器处理 if (e instanceof AccessDeniedException || e instanceof AuthenticationException) { @@ -216,4 +264,4 @@ public class GlobalExceptionHandler { } return group; } -} +} \ No newline at end of file diff --git a/src/main/java/com/youlai/boot/common/result/Result.java b/src/main/java/com/youlai/boot/common/result/Result.java index a464962b..855361da 100644 --- a/src/main/java/com/youlai/boot/common/result/Result.java +++ b/src/main/java/com/youlai/boot/common/result/Result.java @@ -32,11 +32,11 @@ public class Result implements Serializable { } public static Result failed() { - return result(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), ResultCode.SYSTEM_EXECUTION_ERROR.getMsg(), null); + return result(ResultCode.SYSTEM_ERROR.getCode(), ResultCode.SYSTEM_ERROR.getMsg(), null); } public static Result failed(String msg) { - return result(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), msg, null); + return result(ResultCode.SYSTEM_ERROR.getCode(), msg, null); } public static Result judge(boolean status) { diff --git a/src/main/java/com/youlai/boot/common/result/ResultCode.java b/src/main/java/com/youlai/boot/common/result/ResultCode.java index 3b92e4ab..16d3e83a 100644 --- a/src/main/java/com/youlai/boot/common/result/ResultCode.java +++ b/src/main/java/com/youlai/boot/common/result/ResultCode.java @@ -10,7 +10,7 @@ import java.io.Serializable; *

* 参考阿里巴巴开发手册响应码规范 * - * @author Ray + * @author Ray.Hao * @since 2020/6/23 **/ @AllArgsConstructor @@ -19,57 +19,183 @@ public enum ResultCode implements IResultCode, Serializable { SUCCESS("00000", "一切ok"), + /** 一级宏观错误码 */ USER_ERROR("A0001", "用户端错误"), - REPEAT_SUBMIT_ERROR("A0002", "您的请求已提交,请不要重复提交或等待片刻再尝试。"), - USER_LOGIN_ERROR("A0200", "用户登录异常"), + /** 二级宏观错误码 */ + USER_REGISTRATION_ERROR("A0100", "用户注册错误"), + USER_NOT_AGREE_PRIVACY_AGREEMENT("A0101", "用户未同意隐私协议"), + REGISTRATION_COUNTRY_OR_REGION_RESTRICTED("A0102", "注册国家或地区受限"), - USER_NOT_EXIST("A0201", "用户不存在"), - USER_ACCOUNT_LOCKED("A0202", "用户账户被冻结"), - USER_ACCOUNT_INVALID("A0203", "用户账户已作废"), + USERNAME_VERIFICATION_FAILED("A0110", "用户名校验失败"), + USERNAME_ALREADY_EXISTS("A0111", "用户名已存在"), + USERNAME_CONTAINS_SENSITIVE_WORDS("A0112", "用户名包含敏感词"), + USERNAME_CONTAINS_SPECIAL_CHARACTERS("A0113", "用户名包含特殊字符"), - USERNAME_OR_PASSWORD_ERROR("A0210", "用户名或密码错误"), - PASSWORD_ENTER_EXCEED_LIMIT("A0211", "用户输入密码次数超限"), - CLIENT_AUTHENTICATION_FAILED("A0212", "客户端认证失败"), + PASSWORD_VERIFICATION_FAILED("A0120", "密码校验失败"), + PASSWORD_LENGTH_NOT_ENOUGH("A0121", "密码长度不够"), + PASSWORD_STRENGTH_NOT_ENOUGH("A0122", "密码强度不够"), - VERIFY_CODE_TIMEOUT("A0213", "验证码已过期"), - VERIFY_CODE_ERROR("A0214", "验证码错误"), + VERIFICATION_CODE_INPUT_ERROR("A0130", "校验码输入错误"), + SMS_VERIFICATION_CODE_INPUT_ERROR("A0131", "短信校验码输入错误"), + EMAIL_VERIFICATION_CODE_INPUT_ERROR("A0132", "邮件校验码输入错误"), + VOICE_VERIFICATION_CODE_INPUT_ERROR("A0133", "语音校验码输入错误"), - TOKEN_INVALID("A0230", "token无效或已过期"), - REFRESH_TOKEN_INVALID("A0231", "刷新token无效或已过期"), + USER_CERTIFICATE_EXCEPTION("A0140", "用户证件异常"), + USER_CERTIFICATE_TYPE_NOT_SELECTED("A0141", "用户证��类型未选择"), + MAINLAND_ID_NUMBER_VERIFICATION_ILLEGAL("A0142", "大陆身份证编号校验非法"), - TOKEN_ACCESS_FORBIDDEN("A0232", "token已被禁止访问"), + USER_BASIC_INFORMATION_VERIFICATION_FAILED("A0150", "用户基本信息校验失败"), + PHONE_FORMAT_VERIFICATION_FAILED("A0151", "手机格式校验失败"), + ADDRESS_FORMAT_VERIFICATION_FAILED("A0152", "地址格式校验失败"), + EMAIL_FORMAT_VERIFICATION_FAILED("A0153", "邮箱格式校验失败"), + /** 二级宏观错误码 */ + USER_LOGIN_EXCEPTION("A0200", "用户登录异常"), + USER_ACCOUNT_FROZEN("A0201", "用户账户被冻结"), + USER_ACCOUNT_ABOLISHED("A0202", "用户账户已作废"), - AUTHORIZED_ERROR("A0300", "访问权限异常"), + USER_PASSWORD_ERROR("A0210", "用户名或密码错误"), + USER_INPUT_PASSWORD_ERROR_LIMIT_EXCEEDED("A0211", "用户输入密码错误次数超限"), + + USER_IDENTITY_VERIFICATION_FAILED("A0220", "用户身份校验失败"), + USER_FINGERPRINT_RECOGNITION_FAILED("A0221", "用户指纹识别失败"), + USER_FACE_RECOGNITION_FAILED("A0222", "用户面容识别失败"), + USER_NOT_AUTHORIZED_THIRD_PARTY_LOGIN("A0223", "用户未获得第三方登录授权"), + + ACCESS_TOKEN_INVALID("A0230", "访问令牌无效或已过期"), + REFRESH_TOKEN_INVALID("A0231", "刷新令牌无效或已过期"), + + // 验证码错误 + USER_VERIFICATION_CODE_ERROR("A0240", "用户验证码错误"), + USER_VERIFICATION_CODE_ATTEMPT_LIMIT_EXCEEDED("A0241", "用户验证码尝试次数超限"), + USER_VERIFICATION_CODE_EXPIRED("A0242", "用户验证码过期"), + + /** 二级宏观错误码 */ + ACCESS_PERMISSION_EXCEPTION("A0300", "访问权限异常"), ACCESS_UNAUTHORIZED("A0301", "访问未授权"), - FORBIDDEN_OPERATION("A0302", "演示环境禁止新增、修改和删除数据,请本地部署后测试"), + AUTHORIZATION_IN_PROGRESS("A0302", "正在授权中"), + USER_AUTHORIZATION_APPLICATION_REJECTED("A0303", "用户授权申请被拒绝"), + ACCESS_OBJECT_PRIVACY_SETTINGS_BLOCKED("A0310", "因访问对象隐私设置被拦截"), + AUTHORIZATION_EXPIRED("A0311", "授权已过期"), + NO_PERMISSION_TO_USE_API("A0312", "无权限使用 API"), - PARAM_ERROR("A0400", "用户请求参数错误"), - RESOURCE_NOT_FOUND("A0401", "请求资源不存在"), - PARAM_IS_NULL("A0410", "请求必填参数为空"), + USER_ACCESS_BLOCKED("A0320", "用户访问被拦截"), + BLACKLISTED_USER("A0321", "黑名单用户"), + ACCOUNT_FROZEN("A0322", "账号被冻结"), + ILLEGAL_IP_ADDRESS("A0323", "非法 IP 地址"), + GATEWAY_ACCESS_RESTRICTED("A0324", "网关访问受限"), + REGION_BLACKLIST("A0325", "地域黑名单"), - USER_UPLOAD_FILE_ERROR("A0700", "用户上传文件异常"), - USER_UPLOAD_FILE_TYPE_NOT_MATCH("A0701", "用户上传文件类型不匹配"), - USER_UPLOAD_FILE_SIZE_EXCEEDS("A0702", "用户上传文件太大"), - USER_UPLOAD_IMAGE_SIZE_EXCEEDS("A0703", "用户上传图片太大"), + SERVICE_ARREARS("A0330", "服务已欠费"), - SYSTEM_EXECUTION_ERROR("B0001", "系统执行出错"), + USER_SIGNATURE_EXCEPTION("A0340", "用户签名异常"), + RSA_SIGNATURE_ERROR("A0341", "RSA 签名错误"), + + /** 二级宏观错误码 */ + USER_REQUEST_PARAMETER_ERROR("A0400", "用户请求参数错误"), + CONTAINS_ILLEGAL_MALICIOUS_REDIRECT_LINK("A0401", "包含非法恶意跳转链接"), + INVALID_USER_INPUT("A0402", "无效的用户输入"), + + REQUEST_REQUIRED_PARAMETER_IS_EMPTY("A0410", "请求必填参数为空"), + + REQUEST_PARAMETER_VALUE_EXCEEDS_ALLOWED_RANGE("A0420", "请求参数值超出允许的范围"), + PARAMETER_FORMAT_MISMATCH("A0421", "参数格式不匹配"), + + USER_INPUT_CONTENT_ILLEGAL("A0430", "用户输入内容非法"), + CONTAINS_PROHIBITED_SENSITIVE_WORDS("A0431", "包含违禁敏感词"), + + USER_OPERATION_EXCEPTION("A0440", "用户操作异常"), + + /** 二级宏观错误码 */ + USER_REQUEST_SERVICE_EXCEPTION("A0500", "用户请求服务异常"), + REQUEST_LIMIT_EXCEEDED("A0501", "请求次数超出限制"), + REQUEST_CONCURRENCY_LIMIT_EXCEEDED("A0502", "请求并发数超出限制"), + USER_OPERATION_PLEASE_WAIT("A0503", "用户操作请等待"), + WEBSOCKET_CONNECTION_EXCEPTION("A0504", "WebSocket 连接异常"), + WEBSOCKET_CONNECTION_DISCONNECTED("A0505", "WebSocket 连接断开"), + USER_DUPLICATE_REQUEST("A0506", "用户重复请求"), + + /** 二级宏观错误码 */ + USER_RESOURCE_EXCEPTION("A0600", "用户资源异常"), + ACCOUNT_BALANCE_INSUFFICIENT("A0601", "账户余额不足"), + USER_DISK_SPACE_INSUFFICIENT("A0602", "用户磁盘空间不足"), + USER_MEMORY_SPACE_INSUFFICIENT("A0603", "用户内存空间不足"), + USER_OSS_CAPACITY_INSUFFICIENT("A0604", "用户 OSS 容量不足"), + USER_QUOTA_EXHAUSTED("A0605", "用户配额已用光"), + USER_RESOURCE_NOT_FOUND("A0606", "用户资源不存在"), + + /** 二级宏观错误码 */ + USER_UPLOAD_FILE_EXCEPTION("A0700", "用户上传文件异常"), + USER_UPLOAD_FILE_TYPE_MISMATCH("A0701", "用户上传文件类型不匹配"), + USER_UPLOAD_FILE_TOO_LARGE("A0702", "用户上传文件太大"), + USER_UPLOAD_IMAGE_TOO_LARGE("A0703", "用户上传图片太大"), + USER_UPLOAD_VIDEO_TOO_LARGE("A0704", "用户上传视频太大"), + USER_UPLOAD_COMPRESSED_FILE_TOO_LARGE("A0705", "用户上传压缩文件太大"), + + /** 二级宏观错误码 */ + USER_CURRENT_VERSION_EXCEPTION("A0800", "用户当前版本异常"), + USER_INSTALLED_VERSION_NOT_MATCH_SYSTEM("A0801", "用户安装版本与系统不匹配"), + USER_INSTALLED_VERSION_TOO_LOW("A0802", "用户安装版本过低"), + USER_INSTALLED_VERSION_TOO_HIGH("A0803", "用户安装版本过高"), + USER_INSTALLED_VERSION_EXPIRED("A0804", "用户安装版本已过期"), + USER_API_REQUEST_VERSION_NOT_MATCH("A0805", "用户 API 请求版本不匹配"), + USER_API_REQUEST_VERSION_TOO_HIGH("A0806", "用户 API 请求版本过高"), + USER_API_REQUEST_VERSION_TOO_LOW("A0807", "用户 API 请求版本过低"), + + /** 二级宏观错误码 */ + USER_PRIVACY_NOT_AUTHORIZED("A0900", "用户隐私未授权"), + USER_PRIVACY_NOT_SIGNED("A0901", "用户隐私未签署"), + USER_CAMERA_NOT_AUTHORIZED("A0903", "用户相机未授权"), + USER_PHOTO_LIBRARY_NOT_AUTHORIZED("A0904", "用户图片库未授权"), + USER_FILE_NOT_AUTHORIZED("A0905", "用户文件未授权"), + USER_LOCATION_INFORMATION_NOT_AUTHORIZED("A0906", "用户位置信息未授权"), + USER_CONTACTS_NOT_AUTHORIZED("A0907", "用户通讯录未授权"), + + /** 二级宏观错误码 */ + USER_DEVICE_EXCEPTION("A1000", "用户设备异常"), + USER_CAMERA_EXCEPTION("A1001", "用户相机异常"), + USER_MICROPHONE_EXCEPTION("A1002", "用户麦克风异常"), + USER_EARPIECE_EXCEPTION("A1003", "用户听筒异常"), + USER_SPEAKER_EXCEPTION("A1004", "用户扬声器异常"), + USER_GPS_POSITIONING_EXCEPTION("A1005", "用户 GPS 定位异常"), + + /** 一级宏观错误码 */ + SYSTEM_ERROR("B0001", "系统执行出错"), + + /** 二级宏观错误码 */ SYSTEM_EXECUTION_TIMEOUT("B0100", "系统执行超时"), - SYSTEM_ORDER_PROCESSING_TIMEOUT("B0100", "系统订单处理超时"), - SYSTEM_DISASTER_RECOVERY_TRIGGER("B0200", "系统容灾功能被触发"), - FLOW_LIMITING("B0210", "系统限流,请稍后再试"), - DEGRADATION("B0220", "系统功能降级"), + /** 二级宏观错误码 */ + SYSTEM_DISASTER_RECOVERY_FUNCTION_TRIGGERED("B0200", "系统容灾功能被触发"), - SYSTEM_RESOURCE_ERROR("B0300", "系统资源异常"), - SYSTEM_RESOURCE_EXHAUSTION("B0310", "系统资源耗尽"), - SYSTEM_RESOURCE_ACCESS_ERROR("B0320", "系统资源访问异常"), - SYSTEM_READ_DISK_FILE_ERROR("B0321", "系统读取磁盘文件失败"), + SYSTEM_RATE_LIMITING("B0210", "系统限流"), - CALL_THIRD_PARTY_SERVICE_ERROR("C0001", "调用第三方服务出错"), + SYSTEM_FUNCTION_DEGRADATION("B0220", "系统功能降级"), + + /** 二级宏观错误码 */ + SYSTEM_RESOURCE_EXCEPTION("B0300", "系统资源异常"), + SYSTEM_RESOURCE_EXHAUSTED("B0310", "系统资源耗尽"), + SYSTEM_DISK_SPACE_EXHAUSTED("B0311", "系统磁盘空间耗尽"), + SYSTEM_MEMORY_EXHAUSTED("B0312", "系统内存耗尽"), + FILE_HANDLE_EXHAUSTED("B0313", "文件句柄耗尽"), + SYSTEM_CONNECTION_POOL_EXHAUSTED("B0314", "系统连接池耗尽"), + SYSTEM_THREAD_POOL_EXHAUSTED("B0315", "系统线程池耗尽"), + + SYSTEM_RESOURCE_ACCESS_EXCEPTION("B0320", "系统资源访问异常"), + SYSTEM_READ_DISK_FILE_FAILED("B0321", "系统读取磁盘文件失败"), + + + /** 一级宏观错误码 */ + THIRD_PARTY_SERVICE_ERROR("C0001", "调用第三方服务出错"), + + /** 二级宏观错误码 */ MIDDLEWARE_SERVICE_ERROR("C0100", "中间件服务出错"), + + RPC_SERVICE_ERROR("C0110", "RPC 服务出错"), + RPC_SERVICE_NOT_FOUND("C0111", "RPC 服务未找到"), + RPC_SERVICE_NOT_REGISTERED("C0112", "RPC 服务未注册"), INTERFACE_NOT_EXIST("C0113", "接口不存在"), MESSAGE_SERVICE_ERROR("C0120", "消息服务出错"), @@ -78,12 +204,56 @@ public enum ResultCode implements IResultCode, Serializable { MESSAGE_SUBSCRIPTION_ERROR("C0123", "消息订阅出错"), MESSAGE_GROUP_NOT_FOUND("C0124", "消息分组未查到"), - DATABASE_ERROR("C0300", "数据库服务出错"), - DATABASE_TABLE_NOT_EXIST("C0311", "表不存在"), - DATABASE_COLUMN_NOT_EXIST("C0312", "列不存在"), - DATABASE_DUPLICATE_COLUMN_NAME("C0321", "多表关联中存在多个相同名称的列"), + CACHE_SERVICE_ERROR("C0130", "缓存服务出错"), + KEY_LENGTH_EXCEEDS_LIMIT("C0131", "key 长度超过限制"), + VALUE_LENGTH_EXCEEDS_LIMIT("C0132", "value 长度超过限制"), + STORAGE_CAPACITY_FULL("C0133", "存储容量已满"), + UNSUPPORTED_DATA_FORMAT("C0134", "不支持的数据格式"), + + CONFIGURATION_SERVICE_ERROR("C0140", "配置服务出错"), + + NETWORK_RESOURCE_SERVICE_ERROR("C0150", "网络资源服务出错"), + VPN_SERVICE_ERROR("C0151", "VPN 服务出错"), + CDN_SERVICE_ERROR("C0152", "CDN 服务出错"), + DOMAIN_NAME_RESOLUTION_SERVICE_ERROR("C0153", "域名解析服务出错"), + GATEWAY_SERVICE_ERROR("C0154", "网关服务出错"), + + /** 二级宏观错误码 */ + THIRD_PARTY_SYSTEM_EXECUTION_TIMEOUT("C0200", "第三方系统执行超时"), + + RPC_EXECUTION_TIMEOUT("C0210", "RPC 执行超时"), + + MESSAGE_DELIVERY_TIMEOUT("C0220", "消息投递超时"), + + CACHE_SERVICE_TIMEOUT("C0230", "缓存服务超时"), + + CONFIGURATION_SERVICE_TIMEOUT("C0240", "配置服务超时"), + + DATABASE_SERVICE_TIMEOUT("C0250", "数据库服务超时"), + + /** 二级宏观错误码 */ + DATABASE_SERVICE_ERROR("C0300", "数据库服务出错"), + + TABLE_NOT_EXIST("C0311", "表不存在"), + COLUMN_NOT_EXIST("C0312", "列不存在"), + + MULTIPLE_SAME_NAME_COLUMNS_IN_MULTI_TABLE_ASSOCIATION("C0321", "多表关联中存在多个相同名称的列"), + DATABASE_DEADLOCK("C0331", "数据库死锁"), - DATABASE_PRIMARY_KEY_CONFLICT("C0341", "主键冲突"); + + PRIMARY_KEY_CONFLICT("C0341", "主键冲突"), + + /** 二级宏观错误码 */ + THIRD_PARTY_DISASTER_RECOVERY_SYSTEM_TRIGGERED("C0400", "第三方容灾系统被触发"), + THIRD_PARTY_SYSTEM_RATE_LIMITING("C0401", "第三方系统限流"), + THIRD_PARTY_FUNCTION_DEGRADATION("C0402", "第三方功能降级"), + + /** 二级宏观错误码 */ + NOTIFICATION_SERVICE_ERROR("C0500", "通知服务出错"), + SMS_REMINDER_SERVICE_FAILED("C0501", "短信提醒服务失败"), + VOICE_REMINDER_SERVICE_FAILED("C0502", "语音提醒服务失败"), + EMAIL_REMINDER_SERVICE_FAILED("C0503", "邮件提醒服务失败"); + @Override public String getCode() { @@ -114,6 +284,6 @@ public enum ResultCode implements IResultCode, Serializable { return value; } } - return SYSTEM_EXECUTION_ERROR; // 默认系统执行错误 + return SYSTEM_ERROR; // 默认系统执行错误 } -} +} \ No newline at end of file diff --git a/src/main/java/com/youlai/boot/common/util/ResponseUtils.java b/src/main/java/com/youlai/boot/common/util/ResponseUtils.java index 4ae24191..45e6b79e 100644 --- a/src/main/java/com/youlai/boot/common/util/ResponseUtils.java +++ b/src/main/java/com/youlai/boot/common/util/ResponseUtils.java @@ -30,8 +30,8 @@ public class ResponseUtils { public static void writeErrMsg(HttpServletResponse response, ResultCode resultCode) { // 根据不同的结果码设置HTTP状态 int status = switch (resultCode) { - case ACCESS_UNAUTHORIZED, TOKEN_INVALID,REFRESH_TOKEN_INVALID -> HttpStatus.UNAUTHORIZED.value(); - case TOKEN_ACCESS_FORBIDDEN -> HttpStatus.FORBIDDEN.value(); + case ACCESS_UNAUTHORIZED, ACCESS_TOKEN_INVALID , REFRESH_TOKEN_INVALID + -> HttpStatus.UNAUTHORIZED.value(); default -> HttpStatus.BAD_REQUEST.value(); }; diff --git a/src/main/java/com/youlai/boot/config/MybatisConfig.java b/src/main/java/com/youlai/boot/config/MybatisConfig.java index e6cb1dac..a92b40f6 100644 --- a/src/main/java/com/youlai/boot/config/MybatisConfig.java +++ b/src/main/java/com/youlai/boot/config/MybatisConfig.java @@ -14,7 +14,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; /** * mybatis-plus 自动配置类 * - * @author haoxr + * @author Ray.Hao * @since 2022/7/2 */ @Configuration diff --git a/src/main/java/com/youlai/boot/config/RedisCacheConfig.java b/src/main/java/com/youlai/boot/config/RedisCacheConfig.java index 17b71038..f1abe126 100644 --- a/src/main/java/com/youlai/boot/config/RedisCacheConfig.java +++ b/src/main/java/com/youlai/boot/config/RedisCacheConfig.java @@ -16,7 +16,7 @@ import org.springframework.data.redis.serializer.RedisSerializer; /** * Redis 缓存配置 * - * @author Ray + * @author Ray.Hao * @since 2023/12/4 */ @EnableCaching diff --git a/src/main/java/com/youlai/boot/config/RedisConfig.java b/src/main/java/com/youlai/boot/config/RedisConfig.java index bdb4fead..a6ab6eb9 100644 --- a/src/main/java/com/youlai/boot/config/RedisConfig.java +++ b/src/main/java/com/youlai/boot/config/RedisConfig.java @@ -9,7 +9,7 @@ import org.springframework.data.redis.serializer.RedisSerializer; /** * Redis 配置 * - * @author Ray + * @author Ray.Hao * @since 2023/5/15 */ @Configuration diff --git a/src/main/java/com/youlai/boot/core/aspect/RepeatSubmitAspect.java b/src/main/java/com/youlai/boot/core/aspect/RepeatSubmitAspect.java index dbf783a2..8d86e474 100644 --- a/src/main/java/com/youlai/boot/core/aspect/RepeatSubmitAspect.java +++ b/src/main/java/com/youlai/boot/core/aspect/RepeatSubmitAspect.java @@ -55,7 +55,7 @@ public class RepeatSubmitAspect { RLock lock = redissonClient.getLock(resubmitLockKey); boolean lockResult = lock.tryLock(0, expire, TimeUnit.SECONDS); // 获取锁失败,直接返回 false if (!lockResult) { - throw new BusinessException(ResultCode.REPEAT_SUBMIT_ERROR); // 抛出重复提交提示信息 + throw new BusinessException(ResultCode.USER_DUPLICATE_REQUEST); // 抛出重复提交提示信息 } } return pjp.proceed(); diff --git a/src/main/java/com/youlai/boot/core/filter/RateLimiterFilter.java b/src/main/java/com/youlai/boot/core/filter/RateLimiterFilter.java index 4441347a..7b4c570d 100644 --- a/src/main/java/com/youlai/boot/core/filter/RateLimiterFilter.java +++ b/src/main/java/com/youlai/boot/core/filter/RateLimiterFilter.java @@ -73,7 +73,7 @@ public class RateLimiterFilter extends OncePerRequestFilter { @NotNull FilterChain filterChain) throws ServletException, IOException { String ip = IPUtils.getIpAddr(request); if (rateLimit(ip)) { - ResponseUtils.writeErrMsg(response, ResultCode.FLOW_LIMITING); + ResponseUtils.writeErrMsg(response, ResultCode.REQUEST_CONCURRENCY_LIMIT_EXCEEDED); return; } filterChain.doFilter(request, response); diff --git a/src/main/java/com/youlai/boot/core/security/filter/CaptchaValidationFilter.java b/src/main/java/com/youlai/boot/core/security/filter/CaptchaValidationFilter.java index d0fabe5c..63737feb 100644 --- a/src/main/java/com/youlai/boot/core/security/filter/CaptchaValidationFilter.java +++ b/src/main/java/com/youlai/boot/core/security/filter/CaptchaValidationFilter.java @@ -55,13 +55,13 @@ public class CaptchaValidationFilter extends OncePerRequestFilter { String verifyCodeKey = request.getParameter(CAPTCHA_KEY_PARAM_NAME); String cacheVerifyCode = (String) redisTemplate.opsForValue().get(SecurityConstants.CAPTCHA_CODE_PREFIX + verifyCodeKey); if (cacheVerifyCode == null) { - ResponseUtils.writeErrMsg(response, ResultCode.VERIFY_CODE_TIMEOUT); + ResponseUtils.writeErrMsg(response, ResultCode.USER_VERIFICATION_CODE_EXPIRED); } else { // 验证码比对 if (codeGenerator.verify(cacheVerifyCode, captchaCode)) { chain.doFilter(request, response); } else { - ResponseUtils.writeErrMsg(response, ResultCode.VERIFY_CODE_ERROR); + ResponseUtils.writeErrMsg(response, ResultCode.USER_VERIFICATION_CODE_ERROR); } } } else { diff --git a/src/main/java/com/youlai/boot/core/security/filter/JwtValidationFilter.java b/src/main/java/com/youlai/boot/core/security/filter/JwtValidationFilter.java index 11f3230b..d85338c9 100644 --- a/src/main/java/com/youlai/boot/core/security/filter/JwtValidationFilter.java +++ b/src/main/java/com/youlai/boot/core/security/filter/JwtValidationFilter.java @@ -48,7 +48,7 @@ public class JwtValidationFilter extends OncePerRequestFilter { // 校验 JWT Token ,包括验签和是否过期 boolean isValidate = jwtTokenService.validateToken(token); if (!isValidate) { - ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID); + ResponseUtils.writeErrMsg(response, ResultCode.ACCESS_TOKEN_INVALID); return; } // 将 Token 解析为 Authentication 对象,并设置到 Spring Security 上下文中 @@ -57,7 +57,7 @@ public class JwtValidationFilter extends OncePerRequestFilter { } } catch (Exception e) { SecurityContextHolder.clearContext(); - ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID); + ResponseUtils.writeErrMsg(response, ResultCode.ACCESS_TOKEN_INVALID); return; } // Token有效或无Token时继续执行过滤链