/**
* @version 2019/8/14
* @description: 异常拦截器
* @modified:
*/
@Slf4j
public class JsonExceptionHandler implements ErrorWebExceptionHandler { /**
* MessageReader
*/
private List<HttpMessageReader<?>> messageReaders = Collections.emptyList(); /**
* MessageWriter
*/
private List<HttpMessageWriter<?>> messageWriters = Collections.emptyList(); /**
* ViewResolvers
*/
private List<ViewResolver> viewResolvers = Collections.emptyList(); /**
* 存储处理异常后的信息
*/
private ThreadLocal<ResEntity> exceptionHandlerResult = new ThreadLocal<>(); /**
* 参考AbstractErrorWebExceptionHandler
*/
public void setMessageReaders(List<HttpMessageReader<?>> messageReaders) {
Assert.notNull(messageReaders, "'messageReaders' must not be null");
this.messageReaders = messageReaders;
} /**
* 参考AbstractErrorWebExceptionHandler
*/
public void setViewResolvers(List<ViewResolver> viewResolvers) {
this.viewResolvers = viewResolvers;
} /**
* 参考AbstractErrorWebExceptionHandler
*/
public void setMessageWriters(List<HttpMessageWriter<?>> messageWriters) {
Assert.notNull(messageWriters, "'messageWriters' must not be null");
this.messageWriters = messageWriters;
} @Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
// 按照异常类型进行处理 默认500
      int httpStatus = HttpStatus.INTERNAL_SERVER_ERROR.value();
      String body = "系统异常,请联系管理员";
      if (ex instanceof NotFoundException) {
      httpStatus = HttpStatus.NOT_FOUND.value();
       body = ex.getMessage();
      }else if(ex instanceof ResponseStatusException){
      ResponseStatusException responseStatusException = (ResponseStatusException) ex;
      httpStatus = responseStatusException.getStatus().value();
      body = responseStatusException.getMessage();
      } else if (ex instanceof BusinessException) {
      body = ex.getMessage();
      httpStatus = ((BusinessException) ex).toResEntity().getHttpStatus();
      } else if (ex instanceof RuntimeException) {
      Throwable cause = ex.getCause();
       body = ex.getMessage();
      if(null != cause && cause.getMessage().contains("Load balancer does not have available server for client")){
       body = "服务不存在";
       }
      }
      //错误记录
ServerHttpRequest request = exchange.getRequest();
log.error("[全局异常处理]异常请求路径:{}", request.getPath());
log.error("异常详细信息:{}",ex);
//封装响应体
ResEntity res = new ResEntity();
res.setHttpStatus(httpStatus);
res.setMsg(body); //参考AbstractErrorWebExceptionHandler
if (exchange.getResponse().isCommitted()) {
return Mono.error(ex);
}
exceptionHandlerResult.set(res);
ServerRequest newRequest = ServerRequest.create(exchange, this.messageReaders);
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse).route(newRequest)
.switchIfEmpty(Mono.error(ex))
.flatMap((handler) -> handler.handle(newRequest))
.flatMap((response) -> write(exchange, response)); } /**
* 参考DefaultErrorWebExceptionHandler
*/
protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
ResEntity result = exceptionHandlerResult.get(); //404 因前端框架问题,不转换处理 ,因此目前只有系统报500才转换为自定义的状态码
if(HttpStatus.INTERNAL_SERVER_ERROR.value() == result.getHttpStatus()){
return ServerResponse.status(HttpStatus.OK.value())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(BodyInserters.fromObject(result));
}
return ServerResponse.status(result.getHttpStatus())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(BodyInserters.fromObject(result));
} /**
* 参考AbstractErrorWebExceptionHandler
*/
private Mono<? extends Void> write(ServerWebExchange exchange,
ServerResponse response) {
exchange.getResponse().getHeaders()
.setContentType(response.headers().getContentType());
return response.writeTo(exchange, new ResponseContext());
} /**
* 参考AbstractErrorWebExceptionHandler
*/
private class ResponseContext implements ServerResponse.Context { @Override
public List<HttpMessageWriter<?>> messageWriters() {
return JsonExceptionHandler.this.messageWriters;
} @Override
public List<ViewResolver> viewResolvers() {
return JsonExceptionHandler.this.viewResolvers;
}
}
}

  

Spring Cloud Gateway之全局异常拦截器的更多相关文章

  1. Spring Cloud Gateway过滤器精确控制异常返回(实战,控制http返回码和message字段)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 前文<Spring Cloud Gat ...

  2. Spring Cloud Gateway过滤器精确控制异常返回(实战,完全定制返回body)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 Spring Cloud Gateway应用 ...

  3. Spring Cloud Gateway的全局异常处理

    Spring Cloud Gateway中的全局异常处理不能直接用@ControllerAdvice来处理,通过跟踪异常信息的抛出,找到对应的源码,自定义一些处理逻辑来符合业务的需求. 网关都是给接口 ...

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

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

  5. Spring Cloud Gateway过滤器精确控制异常返回(分析篇)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 在<Spring Cloud Gate ...

  6. Spring Cloud Gateway之全局过滤器在工作中的使用场景

    一.使用注意事项 1.全局过滤器作用于所有的路由,不需要单独配置. 2.通过@Order来指定执行的顺序,数字越小,优先级越高. 二.默认全局拦截器的整体架构 三.实战场景,例如,校验token.记录 ...

  7. 【Spring Cloud & Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证授权.鉴权的逻辑,结合 ...

  8. Spring Cloud Gateway GatewayFilter的使用

    Spring Cloud Gateway GatewayFilter的使用 一.GatewayFilter的作用 二.Spring Cloud Gateway内置的 GatewayFilter 1.A ...

  9. 看完就会的Spring Cloud Gateway

    在前面几节,我给大家介绍了当一个系统拆分成微服务后,会产生的问题与解决方案:服务如何发现与管理(Nacos注册中心实战),服务与服务如何通信(Ribbon, Feign实战) 今天我们就来聊一聊另一个 ...

随机推荐

  1. python3 int() 各数据类型转int

    print(int('0b1010',0))#二进制数print(int('0xa',0))#十六进制数print(int('0xa',16))print(int('a',16))print(int( ...

  2. Ubuntu18.04安装MySQL(未设置密码或忘记密码)

    一 安装MySQL sudo apt-get update sudo apt-get install mysql-server 二 密码问题 1 安装时提示设置密码 这种情况没什么问题,通过已下命令登 ...

  3. Git基础知识之内部状态管理系统

    本文主要来介绍一下 Git 的内部状态管理系统.它利用基于节点和指针的数据结构来跟踪及管理编辑操作的时间线. 对本地项目而言,任一时刻,Git 处于三种状态中的一种:工作区状态.暂存区状态和提交区状态 ...

  4. 拇指记者深入Android公司,打探事件分发机制背后的秘密

    前言 聊到事件分发,很多朋友就会想到view的dispatchTouchEvent,其实在此之前,Android还做了很多工作. 比如跨进程获取输入事件的方式?在dispatchTouchEvent责 ...

  5. Unity2D项目-平台、解谜、战斗! 1.5 Player框架、技能管理组件

    各位看官老爷们,这里是RuaiRuai工作室,一个做单机游戏的兴趣作坊. 前文提到,凡是有"攻击"语义的对象,在游戏中,我们给予其一个"CanFight"组件予 ...

  6. java反射Array的使用

    1.什么是Array Array是一个类的简写,全限定类名是java.lang.reflect.Array. 2.Array有什么用 Array可以代表所有的数组,可以通过Array动态创建与修改里面 ...

  7. 统计学习方法——实现AdaBoost

    Adaboost 适用问题:二分类问题 模型:加法模型 \[f(x)=\sum_{m=1}^{M} \alpha_{m} G_{m}(x) \] 策略:损失函数为指数函数 \[L(y,f(x))=ex ...

  8. sql指令,增,删,查,改

    增 insert into table (name,sex,age) value('张三','男','20')   向表中的name,sex,age,分别添加张三,男,20的内容 查 select  ...

  9. Kafka2.8安装

    1.概述 最近Kafka官网发布了2.8版本,在该版本中引入了KRaft模式.鉴于新版本和新特性的引入,相关使用资料较少,那边本篇博客笔者将为大家介绍Kafka2.8的安装和使用. 2.内容 2.1  ...

  10. 1113 Integer Set Partition

    Given a set of N (>) positive integers, you are supposed to partition them into two disjoint sets ...