版本: Spring Cloud 2020.0.3

常见的方法有 实现自己的 DefaultErrorWebExceptionHandler 或 仅实现ErrorAttributes.

方法1: ErrorWebExceptionHandler (仅供示意)

自定义一个 GlobalErrorAttributes:


@Component
public class GlobalErrorAttributes extends DefaultErrorAttributes{ @Override
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
Throwable error = super.getError(request); Map<String, Object> map = super.getErrorAttributes(request, options);
map.put("status", HttpStatus.BAD_REQUEST.value());
map.put("message", error.getMessage());
return map;
}
}

实现一个


@Component
@Order(-2)
public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler { public GlobalErrorWebExceptionHandler(GlobalErrorAttributes gea, ApplicationContext applicationContext,
ServerCodecConfigurer serverCodecConfigurer) {
super(gea, new WebProperties.Resources(), applicationContext);
super.setMessageWriters(serverCodecConfigurer.getWriters());
super.setMessageReaders(serverCodecConfigurer.getReaders());
} //渲染html或json
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(final ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
} private Mono<ServerResponse> renderErrorResponse(final ServerRequest request) { final Map<String, Object> errorPropertiesMap = getErrorAttributes(request, ErrorAttributeOptions.defaults()); return ServerResponse.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorPropertiesMap));
}
}

方法2, 仅实现一个 ErrorAttributes, 以覆盖默认的 DefaultErrorAttributes


//Spring 默认的就很好了.
@Component
public class GatewayErrorAttributes extends DefaultErrorAttributes { private static final Logger logger = LoggerFactory.getLogger(GatewayErrorAttributes.class); @Override
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
Throwable error = super.getError(request);
Map<String, Object> errorAttributes = new HashMap<>(8);
errorAttributes.put("message", error.getMessage());
errorAttributes.put("method", request.methodName());
errorAttributes.put("path", request.path()); MergedAnnotation<ResponseStatus> responseStatusAnnotation = MergedAnnotations
.from(error.getClass(), MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).get(ResponseStatus.class); HttpStatus errorStatus = determineHttpStatus(error, responseStatusAnnotation); //必须设置, 否则会报错, 因为 DefaultErrorWebExceptionHandler 的 renderErrorResponse 方法会获取此属性, 重新实现 DefaultErrorWebExceptionHandler也可.
errorAttributes.put("status", errorStatus.value());
errorAttributes.put("code", errorStatus.value()); //html view用
errorAttributes.put("timestamp", new Date());
//html view 用
errorAttributes.put("requestId", request.exchange().getRequest().getId()); errorAttributes.put("error", errorStatus.getReasonPhrase());
errorAttributes.put("exception", error.getClass().getName()); return errorAttributes;
} //从DefaultErrorWebExceptionHandler中复制过来的
private HttpStatus determineHttpStatus(Throwable error, MergedAnnotation<ResponseStatus> responseStatusAnnotation) {
if (error instanceof ResponseStatusException) {
return ((ResponseStatusException) error).getStatus();
}
return responseStatusAnnotation.getValue("code", HttpStatus.class).orElse(HttpStatus.INTERNAL_SERVER_ERROR);
} }

这样就可以了.

注意注意: 必须设置 errorAttributes.put("status", errorStatus.value()) , 否则会报错, 因为 DefaultErrorWebExceptionHandler 的 renderErrorResponse 方法会获取此属性. 除非你自己像方法一一样重新实现 DefaultErrorWebExceptionHandler.

然后在网关中访问一个不存在的服务, 即可看到效果.

curl 'http://127.0.0.1:8900/fundmain22/abc/gogogo?id=1000' --header 'Accept: application/json'
{"exception":"org.springframework.web.server.ResponseStatusException","path":"/fundmain22/abc/gogogo","code":404,"method":"GET","requestId":"094e53e5-1","message":"404 NOT_FOUND","error":"Not Found","status":404,"timestamp":"2021-08-09T11:07:44.106+0000"}

感谢网络上的各种文章...

Spring Cloud Gateway自定义异常处理Exception Handler的更多相关文章

  1. spring cloud gateway自定义过滤器

    在API网关spring cloud gateway和负载均衡框架ribbon实战文章中,主要实现网关与负载均衡等基本功能,详见代码.本节内容将继续围绕此代码展开,主要讲解spring cloud g ...

  2. Spring Cloud Gateway中异常处理

    最近我们的项目在考虑使用Gateway,考虑使用Spring Cloud Gateway,发现网关的异常处理和spring boot 单体应用异常处理还是有很大区别的.让我们来回顾一下异常. 关于异常 ...

  3. Spring Cloud Gateway自定义过滤器实战(观测断路器状态变化)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. Spring Cloud Alibaba学习笔记(21) - Spring Cloud Gateway 自定义全局过滤器

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的全局过滤器,本文介绍如何自定义全局过滤器. 自定义全局过滤需要实现GlobalFilter 接口,该接口和 GatewayFi ...

  5. Spring Cloud Alibaba学习笔记(19) - Spring Cloud Gateway 自定义过滤器工厂

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的内置过滤器工厂,若Spring Cloud Gateway内置的过滤器工厂无法满足我们的业务需求,那么此时就需要自定义自己的过 ...

  6. Spring Cloud Alibaba学习笔记(17) - Spring Cloud Gateway 自定义路由谓词工厂

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的路由谓词工厂,但是如果这些内置的路由谓词工厂不能满足业务需求的话,我们可以自定义路由谓词工厂来实现特定的需求. 例如有某个服务 ...

  7. Spring cloud gateway自定义filter以及负载均衡

    自定义全局filter package com.example.demo; import java.nio.charset.StandardCharsets; import org.apache.co ...

  8. spring cloud gateway 自定义GatewayFilterFactory

    spring cloud gateway提供了很多内置的过滤器,那么因为需求的关系,需要自定义实现,并且要可配置,在一番折腾之后,总算是解决了,那么久记录下来 对于自定义的factory,我们可以选择 ...

  9. 微服务网关实战——Spring Cloud Gateway

    导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...

随机推荐

  1. 面试侃集合 | DelayQueue篇

    面试官:好久不见啊,上次我们聊完了PriorityBlockingQueue,今天我们再来聊聊和它相关的DelayQueue吧. Hydra:就知道你前面肯定给我挖了坑,DelayQueue也是一个无 ...

  2. 『无为则无心』Python序列 — 19、Python列表的其他操作(切片和遍历)

    目录 1.通过切片对列表的操作 (1)通过切片对列表进行修改 (2)通过切片对列表进行删除 (3)注意 2.列表的循环遍历 (1)while循环遍历 (2)for循环遍历 3.列表嵌套 4.综合示例 ...

  3. centos 8.3安装 OPENJDK

    centos 8.3安装 OPENJDK 查找可安装的OPENJDK [root@xamppr10 ~]# yum search java | grep -i --color openjdk 命令执行 ...

  4. 31、DNS介绍

    [root@centos6 ~]# dig @8.8.8.8 www.baidu.com +trace ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.3 ...

  5. layui创建后台框架

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  6. 8、SpringBoot整合之SpringBoot整合MongoDB

    SpringBoot整合MongoDB 一.创建项目,选择依赖 仅选择Spring Web.Spring Data MongoDB即可 二.引入相关依赖(非必要) 这里只是为了实体类的创建方便而引入l ...

  7. CG-CTF WxyVM2

    一.原本以为要动调,因为出现了这个,函数太长,无法反编译 后面才知道这玩意可以在ida的配置文件里面去改,直接改成1024. 里面的MAXFUNSIZE改成1024,就可以反编译了,这个长度是超过这个 ...

  8. 使用xcodeproj 动态插入第三方代码

    # 为什么这么做? 现在有这么一个使用场景,基线能生成项目A,项目B,项目C...如果只有项目A中使用SDK_A,其他项目都不使用,这时候就需要对基线进行差分,只有当我切换到项目A时,才插入SDK_A ...

  9. 等了半年,m1芯片原生支持的.NET IDE出现了

    m1芯片是苹果2020年发布的一款基于arm的桌面芯片,目前已经应用在MacBook Air .MacBook Pro.IMac.Ipad等设备上.可以说整个苹果生态圈都在去intel化. 今年年初跟 ...

  10. python04篇 文件操作(二)、集合

    一.文件操作(二) 1.1 利用with来打开文件 # with open ,python 会自动关闭文件 with open('a.txt', encoding='utf-8') as f: # f ...