spring 引导中的两个从属 Web 客户端 api 调用
Two Dependent web client api calls in spring boot
我有两个 api 调用 我需要根据第一个 api 调用结果获得第二个 api 调用结果 然后我需要合并两个 api 调用回复让我写在这里
Api 调用:https://localhost:8080/projects 这是第一个 api 调用这个结果就像以下
[
{
"projectId" : 2,
"projectName" : "Hello",
"projectDesc" : "Demo project"
},
{
"projectId" : 3,
"projectName" : "Hello123",
"projectDesc" : "Demo project series"
},
{
"projectId" : 4,
"projectName" : "Hello456",
"projectDesc" : "Demo project repeat"
}
]
第二次 api 调用 http://localhost:8080/projectId 在某种意义上 (http://localhost:8080/2)结果如下
[
{
"teamMember" : "abc",
"teamMemberRole": "Manager"
}
]
现在我需要合并两个响应,如何使用 webclient 实现此目的
[
{
"projectId" : 2,
"projectName" : "Hello",
"projectDesc" : "Demo project",
"teamMember" : "abc",
"teamMemberRole" : "Manager"
}
]
感谢您的帮助。提前致谢
我想我理解你的问题,而且它很常见。您想要做的关键事情是创建响应通量,其中每个元素都与子响应的通量合并。即
- 获取项目
- 对于每个项目
- 传递projectId并获取团队成员
- Merge/Map 每个项目有团队成员
- Return 带有团队成员添加数据的项目流量
假设您有一个服务class,它可以获取给定项目的项目和团队成员的数据。
getAllProjects
getTeamMembers
您可以使用它来编写名为“getProjectsWithTeamMembers”的结果函数
@Component
@Slf4j
public class ProjectHandler {
@Autowired
private WebClient webClient;
public Flux<Project> getAllProjects() {
return webClient
.get()
.uri("projects")
.retrieve()
.bodyToFlux(Project.class);
}
public Mono<List<TeamMember>> getTeamMembers(Integer id) {
ParameterizedTypeReference<List<TeamMember>> listParameterizedTypeReference =
new ParameterizedTypeReference<List<TeamMember>>() {
};
return webClient.get()
.uri("" + id)
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse ->
Mono.empty()
)
.bodyToMono(listParameterizedTypeReference)
.log();
}
public Flux<Project> getProjectsWithTeamMembers() {
return getAllProjects()
.flatMap(project ->
Mono.zip(Mono.just(project),
getTeamMembers(project.getProjectId()).defaultIfEmpty(new ArrayList<TeamMember>()))
.map(tuple -> {
log.info("data" + tuple.getT2().size());
return
Project.builder().projectId(tuple.getT1().getProjectId())
.projectName(tuple.getT1().getProjectName())
.projectDesc(tuple.getT1().getProjectDesc())
.teamMemberList(tuple.getT2()).build();
}));
}
}
请注意元组属于
Tuple<Project,List<TeamMember>>
这里你正在做的是使用 Mono.zip 并传递两个东西给它
- 项目
- 团队成员名单
Mono.zip 将合并它并创建项目和团队成员的 Tuple2,您可以使用它来编写映射代码以构建完整的响应。
希望对您有所帮助。
-- 更新 --
下面是更新的代码
网络客户端配置
@Configuration
public class AppConfig {
@Bean
public WebClient webClient(WebClient.Builder webClientBuilder) {
return webClientBuilder
.baseUrl("http://localhost:3000/")
.defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.build();
}
}
型号classes
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Project {
private Integer projectId;
private String projectName;
private String projectDesc;
private List<TeamMember> teamMemberList;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TeamMember {
private String teamMember;
private String teamMemberRole;
}
最后是其余的控制器
@RestController
@Slf4j
public class ProjectController {
@Autowired
private ProjectHandler projectHandler;
@GetMapping(PROJECT_ENDPOINT_V1)
public Flux<Project> getAllProjects() {
return projectHandler.getProjectsWithTeamMembers();
}
}
我有两个 api 调用 我需要根据第一个 api 调用结果获得第二个 api 调用结果 然后我需要合并两个 api 调用回复让我写在这里
Api 调用:https://localhost:8080/projects 这是第一个 api 调用这个结果就像以下
[ {
"projectId" : 2, "projectName" : "Hello", "projectDesc" : "Demo project" }, { "projectId" : 3, "projectName" : "Hello123", "projectDesc" : "Demo project series" }, { "projectId" : 4, "projectName" : "Hello456", "projectDesc" : "Demo project repeat" } ]
第二次 api 调用 http://localhost:8080/projectId 在某种意义上 (http://localhost:8080/2)结果如下
[
{
"teamMember" : "abc",
"teamMemberRole": "Manager"
}
]
现在我需要合并两个响应,如何使用 webclient 实现此目的
[
{
"projectId" : 2,
"projectName" : "Hello",
"projectDesc" : "Demo project",
"teamMember" : "abc",
"teamMemberRole" : "Manager"
}
]
感谢您的帮助。提前致谢
我想我理解你的问题,而且它很常见。您想要做的关键事情是创建响应通量,其中每个元素都与子响应的通量合并。即
- 获取项目
- 对于每个项目
- 传递projectId并获取团队成员
- Merge/Map 每个项目有团队成员
- 对于每个项目
- Return 带有团队成员添加数据的项目流量
假设您有一个服务class,它可以获取给定项目的项目和团队成员的数据。
getAllProjects getTeamMembers
您可以使用它来编写名为“getProjectsWithTeamMembers”的结果函数
@Component
@Slf4j
public class ProjectHandler {
@Autowired
private WebClient webClient;
public Flux<Project> getAllProjects() {
return webClient
.get()
.uri("projects")
.retrieve()
.bodyToFlux(Project.class);
}
public Mono<List<TeamMember>> getTeamMembers(Integer id) {
ParameterizedTypeReference<List<TeamMember>> listParameterizedTypeReference =
new ParameterizedTypeReference<List<TeamMember>>() {
};
return webClient.get()
.uri("" + id)
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse ->
Mono.empty()
)
.bodyToMono(listParameterizedTypeReference)
.log();
}
public Flux<Project> getProjectsWithTeamMembers() {
return getAllProjects()
.flatMap(project ->
Mono.zip(Mono.just(project),
getTeamMembers(project.getProjectId()).defaultIfEmpty(new ArrayList<TeamMember>()))
.map(tuple -> {
log.info("data" + tuple.getT2().size());
return
Project.builder().projectId(tuple.getT1().getProjectId())
.projectName(tuple.getT1().getProjectName())
.projectDesc(tuple.getT1().getProjectDesc())
.teamMemberList(tuple.getT2()).build();
}));
}
}
请注意元组属于
Tuple<Project,List<TeamMember>>
这里你正在做的是使用 Mono.zip 并传递两个东西给它
- 项目
- 团队成员名单
Mono.zip 将合并它并创建项目和团队成员的 Tuple2,您可以使用它来编写映射代码以构建完整的响应。
希望对您有所帮助。
-- 更新 -- 下面是更新的代码
网络客户端配置
@Configuration
public class AppConfig {
@Bean
public WebClient webClient(WebClient.Builder webClientBuilder) {
return webClientBuilder
.baseUrl("http://localhost:3000/")
.defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.build();
}
}
型号classes
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Project {
private Integer projectId;
private String projectName;
private String projectDesc;
private List<TeamMember> teamMemberList;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TeamMember {
private String teamMember;
private String teamMemberRole;
}
最后是其余的控制器
@RestController
@Slf4j
public class ProjectController {
@Autowired
private ProjectHandler projectHandler;
@GetMapping(PROJECT_ENDPOINT_V1)
public Flux<Project> getAllProjects() {
return projectHandler.getProjectsWithTeamMembers();
}
}