首页 > 解决方案 > 使用 Spring boot + WebFlux 进行全局错误处理

问题描述

在 Spring Boot Rest Controller 中使用响应式编程时,我们如何全局处理异常?

我认为这@ControllerAdvice行不通,因为我已经尝试过了,但没有成功。

我的另一个尝试目前是这个选项,使用自定义属性:

@Component
public class OsvcErrorAttributes extends DefaultErrorAttributes {
    public OsvcErrorAttributes() {
        super(true);
    }

    @Override
    public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
        return assembleError(request);
    }

    private Map<String, Object> assembleError(ServerRequest request) {
        ServerException serverException = (ServerException)getError(request);

        Map<String, Object> errorAttributes = new HashMap<>();
        errorAttributes.put("message", serverException.getMessage());
        errorAttributes.put("errors", serverException.getErrorMap());
        return errorAttributes;
    }
}

和 WebExceptionHandler 像这样:

@Component
@Order(-2)
public class OsvcErrorHandler extends AbstractErrorWebExceptionHandler {
    public OsvcErrorHandler(ErrorAttributes errorAttributes,
                            ResourceProperties resourceProperties,
                            ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, applicationContext);

        // TODO: 25.06.2019 temporary workaround
        ServerCodecConfigurer serverCodecConfigurer = new DefaultServerCodecConfigurer();
        setMessageWriters(serverCodecConfigurer.getWriters());
        setMessageReaders(serverCodecConfigurer.getReaders());
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    private Mono<ServerResponse> renderErrorResponse(ServerRequest serverRequest) {

        final Map<String, Object> errorAttributes = getErrorAttributes(serverRequest, true);
        return ServerResponse.status(HttpStatus.BAD_REQUEST)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .body(BodyInserters.fromObject(errorAttributes));
    }
}

产生错误的代码:

@Data
@Service
public class ContactService {
    private final ContactRepository contactRepository;

    public Mono<Business> saveNewContact(Business business) {
        return contactRepository.save(business)
                .onErrorMap(throwable ->
                    ServerException.create(throwable.getMessage())
                        .persistError("ico", business.getIco(), "ICO is probably duplicate"));
    }
}

问题是这也不起作用。我确实遵循了本教程,但我看不出我是否有什么问题。

标签: spring-bootexceptionspring-webfluxproject-reactor

解决方案


您只需像这样在全局错误处理程序构造函数中使用 ServerCodecConfigurer 注入。

public OsvcErrorHandler(GlobalErrorAttributes errorAttributes, ApplicationContext applicationContext, 
                ServerCodecConfigurer serverCodecConfigurer) {
   super(errorAttributes, new ResourceProperties(), applicationContext);
   super.setMessageWriters(serverCodecConfigurer.getWriters());
   super.setMessageReaders(serverCodecConfigurer.getReaders());
}

请在 git存储库中找到代码示例。


推荐阅读