如何将 CustomException 从反应式服务抛出到控制器?

How throws CustomException from reactive service to controller?

我在 0.RestController 中收到一个请求,并将其交给服务进行处理。如果服务没有抛出 exception,我只是 return HttpStatus.200,但是如果服务中发生异常,我需要在控制器中捕获它并且 return 状态取决于异常. 在服务内部,我需要使用 Mono.fromCallable 进行回购访问。好吧,如果找不到用户,我会尝试抛出我的 CustomException,但我无法将其缓存在控制器中。我做错了什么?

控制器:

@RestController
@RequiredArgsConstructor
@Slf4j
public class CardStatusController {

    private final CardStatusService cardStatusService;

    @PostMapping(value = "api/{user_id}/confirm", produces = {MediaType.APPLICATION_JSON_VALUE})
  
    public Mono<ResponseEntity<HttpStatus>> confirmStatus(
            @PathVariable("user_id") String userId,
            @RequestBody CardStatusRequest statusRequest) {
        
        statusRequest.setUserId(userId);
        
        cardStatusService.checkCardStatus(statusRequest);

        return Mono.just(new ResponseEntity<>(HttpStatus.OK));
    }

    @ExceptionHandler({ CheckCardStatusException.class })
    public void handleException() {
        log.error("error!");
    }

我的服务:

    public Mono<Void> checkCardStatus(CardStatusRequest statusRequest) throws CheckCardStatusException {
        if (statusRequest.getCardEmissionStatus().equals(CardEmissionStatus.ACCEPTED)) {
            String reference = statusRequest.getReference();
            return Mono.fromCallable(() -> userRepository.findById(statusRequest.getUserId()))
                    .subscribeOn(Schedulers.boundedElastic())
                    .switchIfEmpty(Mono.error(new CheckCardStatusException(HttpStatus.NOT_FOUND)))
                    .flatMap(user -> Mono.fromCallable(() -> cardRepository.findFireCardByUserId(user.getId()))
                            .flatMap(optionalCard -> {
                                if (optionalCard.isPresent()) {
                                    if (optionalCard.get().getExtId().isEmpty()) {
                                        Card card = optionalCard.get();
                                        card.setExtId(reference);
                                        try {
                                            cardRepository.save(card);
                                        } catch (Exception e) {
                                            return Mono.error(new CheckCardStatusException(HttpStatus.INTERNAL_SERVER_ERROR));
                                        }
                                    } else {
                                        if (!optionalCard.get().getExtId().equals(reference)) {
                                                return Mono.error(new CheckCardStatusException(HttpStatus.CONFLICT));
                                            }
                                    }
                                } else {
                                    Card card = new Card();
                                    //set card params
                                    try {
                                        cardRepository.save(card);
                                    } catch (Exception e) {
                                        return Mono.error(new CheckCardStatusException(HttpStatus.INTERNAL_SERVER_ERROR));
                                    }
                                }
                                return Mono.error(new CheckCardStatusException(HttpStatus.OK));
                            })).then();
        }
        else {
            return Mono.error(new CheckCardStatusException(HttpStatus.OK));
        }
    }
}

我的自定义异常:

@AllArgsConstructor
@Getter
public class CheckCardStatusException extends RuntimeException {
    private HttpStatus httpStatus;
}

checkCardStatus 编辑的 Mono return 从未被订阅,因此错误信号被忽略。您必须 return 整个链到 Webflux 框架如下:

public Mono<ResponseEntity<HttpStatus>> confirmStatus(
        @PathVariable("user_id") String userId,
        @RequestBody CardStatusRequest statusRequest) {
    
    statusRequest.setUserId(userId);
    
    return cardStatusService.checkCardStatus(statusRequest)
            .then(Mono.just(new ResponseEntity<>(HttpStatus.OK)));
}

如果出错,会执行相应的ExceptionHandler