发布作者: Charlotte
百度收录: 正在检测是否收录...
作品采用: 《 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 》许可协议授权
在这次的异常处理中,我实现了一个类为 GatewayExceptionHandler
的全局异常处理器,它使用了 ErrorWebExceptionHandler
接口来对经过网关的请求进行应对的异常处理。
为了便于网关的应用,我为此类添加了 @Component
模式,使得它能被实例化并当作应用程序的 Bean 被引用。
类代码如下:
package com.jingdianjichi.club.gateway.exception;
import cn.dev33.satoken.exception.SaTokenException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jingdianjichi.club.gateway.entity.Result;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
// 获取请求和响应对象
ServerHttpRequest request = serverWebExchange.getRequest();
ServerHttpResponse response = serverWebExchange.getResponse();
Integer code = 200;
String message = "";
// 根据异常类型设置返回的状态码和信息
if (throwable instanceof SaTokenException) {
code = 401; // 无权限
message = "用户无权限";
} else {
code = 500; // 系统错误
message = "系统繁忙";
}
// 创建返回结果对象
Result result = Result.fail(code, message);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
// 将返回的结果转换为JSON格式并写入响应
return response.writeWith(Mono.fromSupplier(() -> {
DataBufferFactory dataBufferFactory = response.bufferFactory();
byte[] bytes = null;
try {
bytes = objectMapper.writeValueAsBytes(result);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return dataBufferFactory.wrap(bytes);
}));
}
}
ServerHttpRequest
和 ServerHttpResponse
:获取请求和响应对象,方便后续处理。instanceof
来判断是否是 SaTokenException
,如果是,就返回401,表示“用户无权限”,否则返回500,表示“系统繁忙”。Result
类来封装返回结果,使返回格式统一。response.getHeaders().setContentType(MediaType.APPLICATION_JSON)
设置返回类型为 JSON。为了方便统一返回的结果信息,我设计了一个全局的 Result
类用于表示结果。
代码如下:
package com.jingdianjichi.club.gateway.entity;
import com.jingdianjichi.club.gateway.ResultCodeEnum;
import lombok.Data;
@Data
public class Result<T> {
private Boolean success; // 是否成功
private Integer code; // 返回码
private String message; // 返回信息
private T data; // 返回的数据内容
// 创建一个失败的结果对象,附带数据
public static <T> Result fail(T data) {
Result result = new Result();
result.setSuccess(false);
result.setCode(ResultCodeEnum.FAIL.getCode());
result.setMessage(ResultCodeEnum.FAIL.desc);
result.setData(data);
return result;
}
// 创建一个通用的失败结果对象
public static Result fail() {
Result result = new Result();
result.setSuccess(false);
result.setCode(ResultCodeEnum.FAIL.getCode());
result.setMessage(ResultCodeEnum.FAIL.desc);
return result;
}
// 创建一个成功的结果对象,附带数据
public static <T> Result ok(T data) {
Result result = new Result();
result.setSuccess(true);
result.setCode(ResultCodeEnum.SUCCESS.getCode());
result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
result.setData(data);
return result;
}
// 创建一个通用的成功结果对象
public static Result ok() {
Result result = new Result();
result.setSuccess(true);
result.setCode(ResultCodeEnum.SUCCESS.getCode());
result.setMessage(ResultCodeEnum.SUCCESS.desc);
return result;
}
// 创建一个自定义错误信息的失败结果对象
public static Result fail(Integer code, String message) {
Result result = new Result();
result.setSuccess(false);
result.setCode(code);
result.setMessage(message);
return result;
}
}
success
:表示操作是否成功的布尔值。code
和 message
:用于描述操作结果的状态码和信息。ok
和 fail
:提供便捷的方法来生成不同的返回结果,便于在代码中使用。为了统一结果码的管理,我使用了一个结果码的枚举类 ResultCodeEnum
,以统一返回码和应对的描述。
代码如下:
package com.jingdianjichi.club.gateway;
import lombok.Getter;
@Getter
public enum ResultCodeEnum {
SUCCESS(200, "成功"),
FAIL(500, "失败");
// 状态码
public int code;
// 描述
public String desc;
ResultCodeEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 根据状态码获取枚举
*/
public static ResultCodeEnum getByCode(int codeVal) {
for (ResultCodeEnum resultCodeEnum : ResultCodeEnum.values()) {
if (resultCodeEnum.code == codeVal) {
return resultCodeEnum;
}
}
return null;
}
}
SUCCESS
和 FAIL
:定义了两种常见的结果码,分别表示成功和失败。getByCode
方法:根据状态码获取对应的枚举值,便于使用。
—— 评论区 ——