Spring 集成 Java DSL:如何循环分页 Rest 服务?

Spring Integration Java DSL: How to loop the paged Rest service?

如何使用 Java DSL Http.outboundGateway 方法循环分页 Rest 服务?

其余URL例如

http://localhost:8080/people?page=3

例如 returns

"content": [
    {"name": "Mike",
     "city": "MyCity"
    },
    {"name": "Peter",
     "city": "MyCity"
    },
    ...
 ]
"pageable": {
    "sort": {
        "sorted": false,
        "unsorted": true
    },
    "pageSize": 20,
    "pageNumber": 3,
    "offset": 60,
    "paged": true,
    "unpaged": false
},
"last": false,
"totalElements": 250,
"totalPages": 13,
"first": false,
"sort": {
    "sorted": false,
    "unsorted": true
},
"number": 3,
"numberOfElements": 20,
"size": 20
}

其中变量 totalPages 表示总页数。

所以如果执行

        integrationFlowBuilder
          .handle(Http
            .outboundGateway("http://localhost:8080/people?page=3")
            .httpMethod(HttpMethod.GET)
            .expectedResponseType(String.class))

访问一个页面,如何循环所有页面?

最简单的方法就是用 @MessagingGateway 包装对 Http.outboundGateway() 的调用,并提供页码作为参数:

@MessagingGateway
public interface HttpPagingGateway {

    @Gateway(requestChannel = "httpPagingGatewayChannel")
    String getPage(int page);

}

然后你得到一个 JSON 作为结果,你可以将它转换成一些域模型或者只执行一个 JsonPathUtils.evaluate()(基于 json-path)来获得的值last 属性以确保您需要为 page++ 调用 getPage()

page 参数将成为要发送的消息的 payload,可以用作 uriVariable:

.handle(Http
        .outboundGateway("http://localhost:8080/people?page={page}")
        .httpMethod(HttpMethod.GET)
        .uriVariable("page", Message::getPayload)
        .expectedResponseType(String.class))

当然,我们可以做类似Spring集成的事情,但是会涉及到filterrouter等一些组件。

更新

首先,我建议您创建一个域模型(一些 Java Bean),比方说 PersonPageResult,以表示 JSON 响应和此类型到 expectedResponseType(PersonPageResult.class) 属性 的 Http.outboundGateway()RestTemplate 和开箱即用的 MappingJackson2HttpMessageConverter 一起可以为您 return 这样的对象作为下游处理的回复。

然后,正如我之前所说,从一些 Java 代码开始循环会更好,您可以将其包装到服务激活器调用中。为此,您应该像这样声明一个网关:

public interface HttpPagingGateway {

    PersonPageResult getPage(int page);

}

注意:完全没有注释。这个技巧是通过 IntegrationFlow:

完成的
@Bean
public IntegrationFlow httpGatewayFlow() {
    return IntegrationFlows.from(HttpPagingGateway.class)
                  .handle(Http
                       .outboundGateway("http://localhost:8080/people?page={page}")
                       .httpMethod(HttpMethod.GET)
                       .uriVariable("page", Message::getPayload)
                       .expectedResponseType(PersonPageResult.class))  
}

参见 IntegrationFlows.from(Class<?> aClass) Java文档。

这样的 HttpPagingGateway 可以通过硬循环逻辑注入到某些服务中:

int page = 1;
boolean last = false;
while(!last) {
  PersonPageResult result = this.httpPagingGateway.getPage(page++);
  last = result.getLast();
  List<Person> persons = result.getPersons();
  // Process persons
}

为了处理那些 persons,我建议有单独的 IntegrationFlow,它也可以从网关开始,或者您可以只发送一个 Message<List<Person>> 到它的输入通道。

这样您将分离分页和处理的关注点,并且在某些 POJO 方法中具有简单的循环逻辑。