From a6a5d42bea1b222a367eea1055b6e774d2f3ae2f Mon Sep 17 00:00:00 2001 From: ayi <2294931964@qq.com> Date: Tue, 3 Feb 2026 16:25:17 +0800 Subject: [PATCH] =?UTF-8?q?gateway=E5=85=A8=E5=B1=80=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xiaoyi/gateway/auth/SaTokenConfigure.java | 7 +- .../gateway/enums/ResponseCodeEnum.java | 29 ++++++++ .../exception/GlobalExceptionHandler.java | 68 +++++++++++++++++++ 3 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/enums/ResponseCodeEnum.java create mode 100644 xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/exception/GlobalExceptionHandler.java diff --git a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/auth/SaTokenConfigure.java b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/auth/SaTokenConfigure.java index 92f2d30..2dd8cbd 100644 --- a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/auth/SaTokenConfigure.java +++ b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/auth/SaTokenConfigure.java @@ -3,7 +3,6 @@ package top.crushtj.xiaoyi.gateway.auth; import cn.dev33.satoken.reactor.filter.SaReactorFilter; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpUtil; -import cn.dev33.satoken.util.SaResult; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -31,7 +30,7 @@ public class SaTokenConfigure { .notMatch("/auth/verification/code/send") // 排除验证码发送接口 .check(r -> StpUtil.checkLogin()) // 校验是否登录 ; - + SaRouter.match("/auth/**", r -> StpUtil.checkPermission("user")); // 权限认证 -- 不同模块, 校验不同权限 // SaRouter.match("/user/**", r -> StpUtil.checkPermission("user")); // SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin")); @@ -39,10 +38,6 @@ public class SaTokenConfigure { // SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders")); // 更多匹配 ... */ - }) - // 异常处理方法:每次setAuth函数出现异常时进入 - .setError(e -> { - return SaResult.error(e.getMessage()); }); } } diff --git a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/enums/ResponseCodeEnum.java b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/enums/ResponseCodeEnum.java new file mode 100644 index 0000000..725a855 --- /dev/null +++ b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/enums/ResponseCodeEnum.java @@ -0,0 +1,29 @@ +package top.crushtj.xiaoyi.gateway.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import top.crushtj.framework.common.exception.BaseExceptionInterface; + +/** + * @author ayi + * @version V1.0 + * @title ResponseCodeEnum + * @date 2026/2/3 16:15 + * @description 异常状态吗枚举 + */ + +@Getter +@AllArgsConstructor +public enum ResponseCodeEnum implements BaseExceptionInterface { + // ----------- 通用异常状态码 ----------- + SYSTEM_ERROR("500", "系统繁忙,请稍后再试"), + UNAUTHORIZED("401", "没有权限"), + + // ----------- 业务异常状态码 ----------- + ; + + // 异常码 + private final String errorCode; + // 错误信息 + private final String errorMessage; +} diff --git a/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/exception/GlobalExceptionHandler.java b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..3a9a985 --- /dev/null +++ b/xiaoyi-gateway/src/main/java/top/crushtj/xiaoyi/gateway/exception/GlobalExceptionHandler.java @@ -0,0 +1,68 @@ +package top.crushtj.xiaoyi.gateway.exception; + +import cn.dev33.satoken.exception.SaTokenException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; +import top.crushtj.framework.common.response.Response; +import top.crushtj.xiaoyi.gateway.enums.ResponseCodeEnum; + +/** + * @author ayi + * @version V1.0 + * @title GlobalExceptionHandler + * @date 2026/2/3 16:17 + * @description 全局异常处理 + */ + +@Slf4j +@Component +public class GlobalExceptionHandler implements ErrorWebExceptionHandler { + + @Resource + private ObjectMapper objectMapper; + + @Override + public Mono handle(ServerWebExchange exchange, Throwable ex) { + // 获取响应对象 + ServerHttpResponse response = exchange.getResponse(); + + log.error("==> 全局异常捕获: ", ex); + + // 响参 + Response result; + // 根据捕获的异常类型,设置不同的响应状态码和响应消息 + if (ex instanceof SaTokenException) { // Sa-Token 异常 + // 权限认证失败时,设置 401 状态码 + response.setStatusCode(HttpStatus.UNAUTHORIZED); + // 构建响应结果 + result = Response.failure(ResponseCodeEnum.UNAUTHORIZED.getErrorCode(), + ResponseCodeEnum.UNAUTHORIZED.getErrorMessage()); + } else { // 其他异常,则统一提示 “系统繁忙” 错误 + result = Response.failure(ResponseCodeEnum.SYSTEM_ERROR); + } + + // 设置响应头的内容类型为 application/json;charset=UTF-8,表示响应体为 JSON 格式 + response.getHeaders() + .setContentType(MediaType.APPLICATION_JSON_UTF8); + // 设置 body 响应体 + return response.writeWith(Mono.fromSupplier(() -> { // 使用 Mono.fromSupplier 创建响应体 + DataBufferFactory bufferFactory = response.bufferFactory(); + try { + // 使用 ObjectMapper 将 result 对象转换为 JSON 字节数组 + return bufferFactory.wrap(objectMapper.writeValueAsBytes(result)); + } catch (Exception e) { + // 如果转换过程中出现异常,则返回空字节数组 + return bufferFactory.wrap(new byte[0]); + } + })); + } +}