当前位置: 首页 > 知识库问答 >
问题:

Springboot外部api调用请求和响应在数据库中捕获

屈俊远
2023-03-14

从我的后端应用程序(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个答案

麻鸿熙
2023-03-14

您可以使用Spring AOP来解决这个交叉问题。

假设ExternalApiCallService是一个spring管理的bean,下面的代码将截获所有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、方面代码已验证其工作正常,并且后来未测试该逻辑。请进行必要的更正

理想情况下,原始方法应该简化为

public ResponseDTOFromExternalApi externalApiCallServiceMethod(String clientId, RequestDTO requestDTO) {

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

更多关于Spring AOP的信息

更新:转念一想,如果所有的外部api调用都通过一个方法,比如ExternalApiCallService.callExternalApi1(),这个日志逻辑可以移动到那个公共点,不是吗?

孟哲
2023-03-14

Spring的WebClient已经能够通过添加exchange筛选器来记录所有请求和响应数据

通过将其用于您的网络请求,唯一要做的就是将此信息写入您的mongoDB。

以下是记录请求和响应的教程:https://www.baeldung.com/spring-log-webclient-calls

干杯

 类似资料:
  • 我有一个带有Rest控制器的Spring启动应用程序,它将接受来自外部方A的超文本传输协议请求。 我想将此请求转发给另一方B。需要捕获来自B响应的数据,然后转发回A。 我最初的想法是通过RestTemplate发出另一个请求,等待响应,捕获必要的数据,然后转发回A。 我只是想知道是否有更巧妙的方法? 提亚

  • 嗨,我正在为后端使用Laravel API,并在React中使用Redux进行登录。嗯,我调用API,我希望laravel API传递正在发生的事情的精确错误,例如用户不存在。问题是当我想在使用axios进行的调用的catch部分访问Mesage时 Laravel登录部分 使用axios响应调用 我在网络控制台中得到的响应 xhr.js:177邮政http://127.0.0.1:8000/api

  • 我正在开发应用程序以从其他站点获取数据并显示在的html表中。 我使用Guzzes发送请求。(stackoverflow问题,最后使用Guzzes) 当我调用基于到外部API的请求时,它向我显示正确的数据! 我的问题是: 当我调用链接以获取laravel中的数据时,它会转到错误。 一些API地址只是在中工作, 我该怎么办?

  • 在实现之前,我正在考虑生成REST API的JSON响应的结构。我在SO上浏览了许多问答,阅读了许多文章、推荐和伪标准。 要求 通知客户一些有用的元信息-HTTP状态代码等。 分页和过滤信息-偏移,限制和过滤查询(API客户端知道影响结果的所有参数)。 关于数据采集的信息-集合中的总记录计数和返回项的数量。API客户端然后能够创建分页。 上一页和下一页的链接(只是考虑,不确定这是否适用于API客户

  • 我正在尝试编写一个扩展,在其中我可以将请求和响应存储在数据库中。我扩展了PostActionServe,现在有两个问题 > 启动模拟服务器后,我向 http://localhost:8089/__admin/mappings 提交了发布请求,但都未调用 doAction 或 doGlobalAction。 现在,如果我到达终点/一些/东西,那么只有全局动作被调用。 我希望当我向mappings A

  • 例如,我试图向www.testjson发出GET请求。com/json,但响应是从不同的域URL检索的,例如www.testjson。com/confirmJson。 Spring mvc是否支持此功能,特别是restTemplate.exchange功能。 我目前正在做这类事情,但我得到一个500状态码(内部服务器错误),无法找出到底是什么导致了错误。 那么RestTemplate真的可以管理重