gateway全局异常处理

This commit is contained in:
2026-02-03 16:25:17 +08:00
parent eaf44e1b4f
commit a6a5d42bea
3 changed files with 98 additions and 6 deletions
@@ -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());
});
}
}
@@ -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;
}
@@ -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<Void> 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]);
}
}));
}
}