spring cloud gateway 全局异常处理

    科技2022-07-11  82

    通常spring boot全局异常捕获我们通常会使用@ControllerAdvice进行全局捕获。放到网关中显然不合适,@ControllerAdvice故名思意,是对controller的一个增强处理。所以在gateway中我们需要如下方式配置:

    网关全局异常配置

    /** * @calssName ExceptionConfig * @Description 网关全局异常配置 * @Author jiangshaoneng * @DATE 2020/9/28 19:36 */ @Configuration @EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class}) public class ExceptionConfig { private final ServerProperties serverProperties; private final ApplicationContext applicationContext; private final ResourceProperties resourceProperties; private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public ExceptionConfig(ServerProperties serverProperties, ResourceProperties resourceProperties, ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) { this.serverProperties = serverProperties; this.applicationContext = applicationContext; this.resourceProperties = resourceProperties; this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) { ExceptionHandler exceptionHandler = new ExceptionHandler( errorAttributes, this.resourceProperties, this.serverProperties.getError(), this.applicationContext); exceptionHandler.setViewResolvers(this.viewResolvers); exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters()); exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders()); return exceptionHandler; } }

    网关全局异常处理类

    对异常返回结果的处理,注意:如果我们对返回的结果进行了加密处理的话,前端接收参数肯定时统一对数据进行解密。所以我们返回的异常信息同样需要加密操作。如果未进行加密处理,则此处无需进行处理。(详细见ExceptionHandler类 response方法) /** * @calssName JsonExceptionHandler * @Description 网关全局异常处理类 * @Author jiangshaoneng * @DATE 2020/9/28 19:35 */ public class ExceptionHandler extends DefaultErrorWebExceptionHandler { public ExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) { super(errorAttributes, resourceProperties, errorProperties, applicationContext); } /** * 获取异常属性 */ @Override protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) { String bgDebug = request.exchange().getAttributeOrDefault(ConstantFilter.BG_DEBUG_KEY, ConstantFilter.REQ_RES_ENCRYPT); int code = 500; Throwable error = super.getError(request); if (error instanceof org.springframework.cloud.gateway.support.NotFoundException) { code = 404; } return response(bgDebug, code, error.getMessage()); } /** * 指定响应处理方法为JSON处理的方法 * @param errorAttributes */ @Override protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse); } /** * 根据code获取对应的HttpStatus * @param errorAttributes */ @Override protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) { int statusCode = 500; Object code = errorAttributes.get("code"); if(code != null){ statusCode = (int) code; } return HttpStatus.valueOf(statusCode); } /** * 构建返回的JSON数据格式 * @param status 状态码 * @param errorMessage 异常信息 * @return */ private static JSONObject response(String bgDebug, int status, String errorMessage) { R r = R.error(status, errorMessage); if(ConstantFilter.REQ_RES_ENCRYPT.equals(bgDebug)){ // 对数据进行加密 String randomKey = AESUtil.getRandomKey(); String encryptData = AESUtil.AESEncrypt(JSONObject.toJSONString(r), randomKey, "CBC"); String encryptRandomKey = RSAUtils.publicEncrypt(randomKey); JSONObject json = new JSONObject(); json.put("k", encryptRandomKey); json.put("v", encryptData); return json; } else { // 无需加密是返回的数据 JSONObject json = new JSONObject(); json.put("code", status); json.put("msg", errorMessage); return json; } } }
    Processed: 0.024, SQL: 8