【SpringCloud】Spring Cloud Gateway 网关全局异常处理

之前前端直接访问后端微服务的Controller接口,如果抛出异常,会自动被编写的全局异常处理器(@ControllerAdvice )捕获返回一个正常的响应,响应的R对象中描述错误信息

@Slf4j//lombok的注解,springboot项目底层默认引入slf4j日志门面+logback日志框架,动态提供
@RestControllerAdvice
//@ControllerAdvice//返回值不会处理为json
public class GlobalExceptionHandler {
  //当Controller抛出异常时,没有被其他ExceptionHandler处理的时候,会被此handler捕获
  @ExceptionHandler(value = Exception.class)//表示异常处理器
  public R exception(Exception e) {
      log.info("异常信息==>>\n" + ExceptionUtils.getStackTrace(e));
      log.warn("异常类型==>>\n" + e.getClass().getName(), new Date());
      return R.error();
  }
  }

现在网关项目的异常没有被处理,直接抛给前端,前端就会出现5xx的服务器错误.
例如:
503:
网关接受到请求时,路由断言成功,可以匹配到路由中的一个微服务的配置
但是网关再注册中心中找不到目标微服务,则报错503

解决方案:
配置网关全局异常处理

  1. 创建自定义异常处理类GlobalJsonExceptionHandler
package com.atlin.guli.infrastructure.apigateway.exception;

import com.atlin.guli.service.base.result.ResultCodeEnum;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.*;

import java.util.HashMap;
import java.util.Map;

/**
 * note_Spring Cloud Gateway 底层使用的WebFlux,全局异常处理不能直接使用 @ControllerAdvice,
 * 可以通过继承DefaultErrorWebExceptionHandler实现自定义异常处理:
 *
 * @author lin
 * @version v1.0
 * @description 自定义 网关全局json异常处理/ 自定义异常处理类GlobalJsonExceptionHandler
 */
public class GlobalJsonExceptionHandler extends DefaultErrorWebExceptionHandler {
    /**
     * 1、指定使用json格式进行响应
     *
     * @param errorAttributes
     * @return
     */
    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        //参数1:匹配所有的请求(所有出现异常的请求)  参数2:指定自己设置响应(默认转为json)
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    /**
     * 2、提供异常数据  : 响应报文数据
     *
     * @param request           request
     * @param includeStackTrace includeStackTrace
     * @return
     */
    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
        // 响应报文的参数:code  message  data     如果需要设置R对象:我们需要封装R对象的属性设置到data属性中
        Map<String, Object> map = new HashMap<>();
        //服务器内部错误
        map.put("code", 500);
        Throwable error = getError(request);//获取请求中的异常信息
        if (error instanceof NotFoundException) {
            map.put("code", 404);
        }
        map.put("message", error.getMessage());
        Map<String, Object> rMap = new HashMap<>();//R对象

        rMap.put("code", ResultCodeEnum.API_GATEWAY_GLOBAL_ERROR.getCode());
        rMap.put("success", ResultCodeEnum.API_GATEWAY_GLOBAL_ERROR.getSuccess());
        rMap.put("message", ResultCodeEnum.API_GATEWAY_GLOBAL_ERROR.getMessage());
        map.put("data", rMap);
        return map;
    }

    /**
     * 3、提供响应报文的状态码
     *
     * @param errorAttributes
     * @return
     */
    @Override
    protected int getHttpStatus(Map<String, Object> errorAttributes) {
        // errorAttributes代表上面方法中封装的响应数据
        int code = (int) errorAttributes.get("code");
        return HttpStatus.valueOf(code).value();
    }

    public GlobalJsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }
}

  1. 使用自定义异常处理覆盖默认异常处理
  /**
     * 将bean注入到容器中的方式:
     * 1、xml配置文件bean标签
     * 2、组件注解
     * 3、组件类中通过@Bean标注的方法返回值
     */
    @Bean
//    @Order(-1) //设置优先级
    public DefaultErrorWebExceptionHandler defaultErrorWebExceptionHandler(
            ErrorAttributes errorAttributes,
            org.springframework.boot.autoconfigure.web.ResourceProperties resourceProperties,
            ServerProperties serverProperties,
            ObjectProvider<ViewResolver> viewResolvers,
            ServerCodecConfigurer serverCodecConfigurer,
            ApplicationContext applicationContext
    ) {

        GlobalJsonExceptionHandler exceptionHandler = new GlobalJsonExceptionHandler(
                errorAttributes,
                resourceProperties,
                serverProperties.getError(),
                applicationContext);

        exceptionHandler.setViewResolvers(viewResolvers.orderedStream().collect(Collectors.toList()));
        exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
        exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());

        return exceptionHandler;
    }
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值