MST

星途 面试题库

面试题:Java Spring框架异常处理机制在微服务架构中的优化策略

在Spring Boot构建的微服务架构中,各个微服务之间通过Feign进行调用,当出现远程调用异常、服务内部业务异常等不同类型异常时,如何设计一个统一且高效的异常处理机制,既能保证异常信息在微服务间准确传递,又能对客户端提供友好的错误反馈,同时兼顾系统的可维护性和扩展性。
31.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 全局异常处理器
    • 在每个微服务中创建全局异常处理器,使用@ControllerAdvice注解。例如:
    @ControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler(FeignException.class)
        @ResponseBody
        public ResponseEntity<ErrorResponse> handleFeignException(FeignException ex) {
            ErrorResponse errorResponse = new ErrorResponse();
            errorResponse.setErrorCode("FEIGN_001");
            errorResponse.setErrorMessage("远程调用异常");
            errorResponse.setDetails(ex.getMessage());
            return new ResponseEntity<>(errorResponse, HttpStatus.valueOf(ex.status()));
        }
        @ExceptionHandler(BusinessException.class)
        @ResponseBody
        public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {
            ErrorResponse errorResponse = new ErrorResponse();
            errorResponse.setErrorCode("BUSINESS_001");
            errorResponse.setErrorMessage("业务异常");
            errorResponse.setDetails(ex.getMessage());
            return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
        }
    }
    
    • 这里ErrorResponse是自定义的错误响应类,包含错误码、错误信息和详细描述。
  2. 自定义异常类
    • 定义业务异常类,例如:
    public class BusinessException extends RuntimeException {
        public BusinessException(String message) {
            super(message);
        }
    }
    
    • 这样在业务代码中,当业务逻辑出现异常时,可以抛出BusinessException
  3. Feign异常处理
    • Feign默认的异常处理比较简单,我们可以自定义ErrorDecoder
    public class CustomErrorDecoder implements ErrorDecoder {
        @Override
        public Exception decode(String methodKey, Response response) {
            try {
                String body = Util.toString(response.body().asReader());
                ErrorResponse errorResponse = new ObjectMapper().readValue(body, ErrorResponse.class);
                // 根据不同的错误码返回不同的异常
                if ("FEIGN_001".equals(errorResponse.getErrorCode())) {
                    return new FeignException.FeignClientException(response.status(), errorResponse.getErrorMessage(), response.request(), null);
                }
                return new FeignException.GenericFeignException(response.status(), errorResponse.getErrorMessage(), response.request(), null);
            } catch (IOException e) {
                return new FeignException.GenericFeignException(response.status(), "解析错误", response.request(), null);
            }
        }
    }
    
    • 然后在Feign客户端配置中使用这个ErrorDecoder
    @Configuration
    public class FeignConfig {
        @Bean
        public ErrorDecoder errorDecoder() {
            return new CustomErrorDecoder();
        }
    }
    
  4. 异常信息传递
    • 在Feign调用时,将异常信息封装在响应体中传递。例如,在被调用方的全局异常处理器中,将异常信息封装到ErrorResponse并返回。
    • 调用方通过自定义的ErrorDecoder解析响应体中的异常信息,并抛出相应的异常,最终由调用方的全局异常处理器处理并返回友好的错误反馈给客户端。
  5. 可维护性和扩展性
    • 通过这种分层的异常处理机制,每个微服务的异常处理逻辑相对独立,便于维护。
    • 当有新的异常类型出现时,只需在全局异常处理器中添加对应的@ExceptionHandler方法,以及在自定义ErrorDecoder中添加相应的处理逻辑,即可实现扩展。