Springboot внешний запрос вызова API и захват ответа в базе данных - PullRequest
0 голосов
/ 01 февраля 2020

Из моего внутреннего приложения ( springboot, java8 ) я сделаю несколько внешних вызовов API. У меня есть требование записать все запросы и данные ответов (включая заголовки, тело запроса и ответа) в базу данных ( MongoDB ).

Ниже приведен мой пример кода, так я пытаюсь перехватить запросы и ответы на каждый внешний вызов API. В случае исключения я сохраню статус «Сбой».

В моем проекте будет добавлено несколько модулей для новой интеграции API сторонних производителей, поэтому в каждом модуле для каждого внешнего вызова API я должен собирать все запросы и ответы, как это. Я не удовлетворен подходом ниже. Пожалуйста, предложите лучший подход для решения этой проблемы.

Пример метода уровня обслуживания

public ResponseDTOFromExternalApi externalApiCallServiceMethod(String clientId, RequestDTO requestDTO) {

        ExternalApiCallRequestObj externalApiCallRequestObj = prepareExternalApiRequestObjFromRequestDTO(requestDTO);
        ApiCall apiCall = ApiCall.builder()
                .clientId(clientId)
                .status("SUBMITTED")
                .requestPayload(externalApiCallRequestObj)
                .build();

        apiCall = apiCallRepository.save(apiCall);

        ExternalApiCallReponseObj externalApiCallReponseObj = externalApiCallService.callExternalApi1(externalApiCallRequestObj);

        apiCall = apiCallRepository.findById(apiCall.getId());

        apiCall.setResponsePayload(externalApiCallReponseObj);
        apiCall.setStatus("COMPLETED");

        apiCallRepository.save(apiCall);

        return toDTO(externalApiCallReponseObj);
}

Пример домена для вызовов API

@Document("api_calls")
@Builder
@Data
public class ApiCall {

    @Id
    private String id;

    private String clientId;

    private String status;

    private Object requestPayload;

    private Object responsePayload;

}

Ответы [ 2 ]

0 голосов
/ 01 февраля 2020

Spring WebClient уже имеет возможность регистрировать все данные запросов и ответов, добавляя фильтры обмена.

При использовании его для сетевых запросов единственное, что остается сделать, - записать эту информацию в свой mongodb.

Вот учебник по ведению журнала запросов и ответов: https://www.baeldung.com/spring-log-webclient-calls

Приветствия

0 голосов
/ 01 февраля 2020

Вы можете использовать Spring AOP для решения этой сквозной проблемы.

Если предположить, что ExternalApiCallService - это управляемый компонентом Spring, следующий код будет перехватывать все callExternalApi1() и может регистрировать то же самое в базе данных.

@Component
@Aspect
public class ExternalCallLoggerAspect {

    @Autowired
    ApiCallRepository apiCallRepository;

    @Pointcut("execution(* *..ExternalApiCallService.callExternalApi1(..))")
    public void externalApiCallService(){}


    @Around("externalApiCallService() && args(request)")
    public ExternalApiCallReponseObj logCalls(ProceedingJoinPoint pjp,ExternalApiCallRequestObj request){

      Object result=null;
      String status = "COMPLETED";
      ExternalApiCallReponseObj response = null;

        // Build the apiCall from request 
        ApiCall apiCall = ApiCall.builder()
                .clientId(clientId)
                .status("SUBMITTED")
                .requestPayload(request)
                .build();

        //save the same to db
        apiCall = apiCallRepository.save(apiCall);

        // Proceed to call the external Api and get the result
        try {
           result = pjp.proceed();
        } catch (Throwable e) {
           status = "FAILED";
        }

        //Update the response           
        apiCall = apiCallRepository.findById(apiCall.getId());            
        apiCall.setStatus(status);
        apiCallRepository.save(apiCall);

        if(result != null) {
          response = (ExternalApiCallReponseObj)result;
          apiCall.setResponsePayload(response);
        }

        //continue with response
        return response;
    }

}

Примечание

1.В опечатке с именем ExternalApiCallReponseObj

2. Проверяется, что код аспекта работает и логика c включена позже непроверенный. Пожалуйста, внесите необходимые исправления

В идеале оригинальный метод должен быть сокращен до этого

public ResponseDTOFromExternalApi externalApiCallServiceMethod(String clientId, RequestDTO requestDTO) {

       return toDTO(externalApiCallService.callExternalApi1(prepareExternalApiRequestObjFromRequestDTO(requestDTO)));
}

Подробнее о Spring AOP здесь


Обновление: , если подумать, если все внешние вызовы API выполняются через один метод, скажем, ExternalApiCallService.callExternalApi1(), эти логи логирования c можно переместить в эту общую точку, не так ли?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...