Spring реактор: это правильный способ вызывать последовательно удаленный API? - PullRequest
0 голосов
/ 21 марта 2019

Я подхожу к конструкции реактора Spring и создаю «Api Composer», который вызывает различные микросервисы через Webflux.

По сути, мне нужно вызвать службу Учетная запись с произвольным apiToken и, если получен HTTP 401 - Unauthorized , он будет преобразован в пользовательское исключение, которое вызовет вызов microservice Token для его обновления и вызова службы Account с обновленным токеном.

Я нашел это решение, которое работает, но я не уверен, что это правильный способ выполнить эту задачу.

Класс маршрутизатора

@Configuration
public class MyRouter {

@Bean
public RouterFunction<ServerResponse> route(MyHandler handler) {
    return RouterFunctions.route(POST("/lineAuthentication").and(accept(APPLICATION_XML)).and(contentType(APPLICATION_XML)), handler::lineAuthentication)
            .andRoute(POST("/anotherMethod").and(accept(APPLICATION_XML)).and(contentType(APPLICATION_XML)), handler::checkPin);
    }
}

Обслуживание учетной записи

    public Mono<LineAuthenticationResponse> lineAuthentication(String apiToken, String businessId, String ip, String channel, boolean forceOk) {

    return webClient.post()
            .uri(builder -> builder.path("account/lineAuthentication")
                    .queryParam("ip", ip)
                    .build())
            .header("businessId", businessId)
            .retrieve()
            .onStatus(status -> status == HttpStatus.UNAUTHORIZED, response -> Mono.error(new ExpiredTokenException(response.statusCode(), "token Expired")))
            .bodyToMono(LineAuthenticationResponse.class);
}

Служба токенов

public Mono<TokenAdapterResponse> getToken(String businessId) {
    Mono<TokenAdapterResponse> tokenMono = webClient.get()
            .uri("token/getToken")
            .retrieve()
            .bodyToMono(TokenAdapterResponse.class);
    return tokenMono;
}

MyHandler

public Mono<ServerResponse> lineAuthentication(ServerRequest serverRequest) {
    .....
    Mono<LineAuthentication> lineDataRequest = serverRequest.bodyToMono(LineAuthentication.class);
    generatedBusinessId = generateBusinessId();
    Mono<ServerResponse> lineAuthenticationResponse = lineDataRequest.flatMap(lineData -> ok().contentType(APPLICATION_XML)
            .body(fromPublisher(
                    handleLineAuthRequest(apiToken, generatedBusinessId, lineData.getServiceData().getIp(), lineData.getServiceData().getChannel(), false).onErrorResume(
                            ExpiredTokenException.class,
                            e -> handleTokenExpiredException(generatedBusinessId, lineData.getServiceData().getIp(), lineData.getServiceData().getChannel())),
                    LineAuthenticationResponse.class)))
            .switchIfEmpty(notFound().build());

    return lineAuthenticationResponse;
}

private Mono<LineAuthenticationResponse> handleLineAuthRequest(String apiKey, String businessId, String ip, String channel, boolean forceOk) {
    System.out.println("handling Line Authentication request");
    return accountService.lineAuthentication(apiToken, businessId, ip, channel, forceOk);
}

private Mono<LineAuthenticationResponse> handleTokenExpiredException(String generatedBusinessId, String ip, String channel) {
    System.out.println("Expired token exception caugth");
    Mono<TokenAdapterResponse> tokenMono = tokenService.getToken(generatedBusinessId).doOnNext(newToken -> updateApiToken(newToken.getResponse().getAccess_token()));
    Mono<LineAuthenticationResponse> map = tokenMono
            .zipWhen(tokenResp -> handleLineAuthRequest(tokenResp.getResponse().getAccess_token(), generatedBusinessId, ip, channel, true)).map(tuple -> {
                tuple.getT1();
                tuple.getT2();
                return tuple.getT2();
            });
    return map;

}

В конце концов, если последовательность вызываемых микросервисов велика, что может быть лучшим способом их последовательного вызова?

A -> B -> C (B не может быть вызван до A, и C не может быть вызван до B).

...