spring-cloud - Spring Cloud Gateway 全局异常处理和自定义错误响应
问题描述
我有一个自定义过滤器,在使用 Spring Cloud Gateway 调用实际 API 之前对每个请求进行身份验证。Spring Cloud 中是否有任何方法可以像 Spring 提供 @ControllerAdvice 一样集中处理异常?我想全局处理异常并从网关返回自定义错误响应。
解决方案
一旦您的身份验证过滤器引发异常,您可以通过覆盖 DefaultErrorAttributes 类来自定义错误响应。
@Component
public class GlobalErrorAttributes extends DefaultErrorAttributes {
private static final Logger logger = LoggerFactory.getLogger(GlobalErrorAttributes.class);
public GlobalErrorAttributes() {
}
public GlobalErrorAttributes(boolean includeException) {
super(includeException);
}
@Override
public Map<String, Object> getErrorAttributes(ServerRequest request,
boolean includeStackTrace) {
Throwable error = this.getError(request);
logger.error("Error occured", error);
MergedAnnotation<ResponseStatus> responseStatusAnnotation = MergedAnnotations
.from(error.getClass(), MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).get(ResponseStatus.class);
HttpStatus errorStatus = findHttpStatus(error, responseStatusAnnotation);
logger.info("errorStatus: {}", errorStatus);
Map<String, Object> map = super.getErrorAttributes(request, includeStackTrace);
String errorCode = getErrorCode(map, errorStatus);
map.remove("timestamp");
map.remove("path");
map.remove("error");
map.remove("requestId");
map.put("errorCode", errorCode);
return map;
}
private HttpStatus findHttpStatus(Throwable error, MergedAnnotation<ResponseStatus> responseStatusAnnotation) {
if (error instanceof ResponseStatusException) {
return ((ResponseStatusException) error).getStatus();
}
return responseStatusAnnotation.getValue("code", HttpStatus.class).orElse(INTERNAL_SERVER_ERROR);
}
private String getErrorCode(Map<String, Object> map, HttpStatus errorStatus) {
String errorCode;
switch (errorStatus) {
case UNAUTHORIZED:
errorCode = "401 UnAuthorized";
break;
case NOT_FOUND:
logger.error("The url:{} is not found", map.get("path"));
errorCode = "404 Not Found";
map.put(MESSAGE, "NOT FOUND");
break;
case METHOD_NOT_ALLOWED:
logger.error("Invalid HTTP Method type for the url: {}", map.get("path"));
errorCode = "405 Method Not Allowed";
break;
default:
logger.error("Unexpected error happened");
logger.error("errorstatus is : {}", errorStatus);
errorCode = "500 Internal Server Error";
map.put(MESSAGE, "Unexpected Error");
}
return errorCode;
}
}
输出将如下所示:
{
"status": 401,
"message": "Invalid Access Token",
"error_code": "401 UnAuthorized"
}
推荐阅读
- ios - Facebook、Twitter、Google+ 等社交媒体链接未在 iOS 的 NativeScript Webview 中打开
- highcharts - highstock - 添加超过 1000 点的注释
- docker - Kubernetes:使用“最新”标签时 kubectl apply 不会更新 pod
- r - str_remove 到多行字符串的结尾
- tomcat - 多个 tomcat 实例更新 - 如何?
- processbuilder - 在 Java 6 中实现 `Process.waitFor(long timeout, TimeUnit unit)`
- c# - 将带有 iText7 的链接添加到 PDF 的页眉或页脚
- google-assistant-sdk - 使 Google Home 实时说话的最佳方法是什么
- sass - 特殊字符和 PurgeCSS 未按预期工作
- jquery - 无限滚动滑块,让DIV无限