这是要求:
- 创建新客户端
- 如果DTO中存在客户推荐,则创建新客户推荐。
- 如果DTO中存在客户次要联系人,则创建客户次要联系人
- 如果DTO中存在客户电话,则创建客户电话
- 不确定如何在响应式流中应用if条件。
- 是否有更好的方法来做到这一点?
- 在此处,除第一个操作外,所有其他操作都可以并行运行。
public Mono<ServerResponse> createClientProfile(ServerRequest request) {
return secContext.retrieveUser().flatMap(usr -> {
return request.bodyToMono(ClientDto.class).flatMap(client -> {
return toNewClient(client, usr).flatMap(clientRepository::save).flatMap(clientRes -> {
return toNewClientReferral(clientRes.getClientId(), client.getDiscount(), usr)
.flatMap(clientReferralRepository::save).flatMap(clientReferralRes -> {
return toNewClientSyContact(clientRes.getClientId(), client.getSecondary(), usr)
.flatMap(clientSyContactRepository::save).flatMap(clientSyContactRes -> {
return clientPhoneRepository
.saveAll(toNewClientPhone(clientRes.getClientId(), client.getPhones(), usr))
.collectList().flatMap(phoneRes -> {
return ServerResponse
.created(URI.create(String.format(CLIENT_URI_FORMAT,
clientRes.getClientId())))
.contentType(APPLICATION_JSON).build();
});
});
});
});
});
});
}
private Mono<Referral> toNewClientReferral(final long clientId, final Discount dto) {
Referral referral = Referral.of(clientId,
dto.getName(), dto.getType(), dto.getAmount(), dto.getStatus());
return Mono.just(referral);
}
client.getDiscount() 可能为空,
client.getSecondary() 可能为空, client.getPhones() 可能为空。
我使用了3个不同的方法来分开流程。
public void createSyContact(ServerRequest request, long clientId) {
secContext.retrieveUser().flatMap(usr -> {
return request.bodyToMono(ClientDto.class).flatMap(client -> {
if (client.getSecondary() != null) {
return toNewClientSyContact(clientId, client.getSecondary(), usr)
.flatMap(clientSyContactRepository::save).flatMap(clientRes -> {
return Mono.just(clientRes.getClientId());
});
} else {
return Mono.empty();
}
});
});
}
public void createReferral(ServerRequest request, long clientId) {
secContext.retrieveUser().flatMap(usr -> {
return request.bodyToMono(ClientDto.class).flatMap(client -> {
if (client.getDiscount() != null) {
return toNewClientReferral(clientId, client.getDiscount(), usr)
.flatMap(clientReferralRepository::save).flatMap(clientRes -> {
return Mono.just(clientRes.getClientId());
});
} else {
return Mono.empty();
}
});
});
}
public Mono<Long> createClientWithPhones(ServerRequest request) {
return secContext.retrieveUser().flatMap(usr -> {
return request.bodyToMono(ClientDto.class).flatMap(client -> {
return toNewClient(client, usr).flatMap(clientRepository::save).flatMap(clientRes -> {
return clientPhoneRepository
.saveAll(toNewClientPhone(clientRes.getClientId(), client.getPhones(), usr)).collectList()
.flatMap(phoneRes -> {
return Mono.just(clientRes.getClientId());
});
});
});
});
}
在这里,createClientWithPhones是必需的,因此不需要进行if检查。但是另外两种方法createReferral和createSyContact需要进行if检查。需要先执行createClientWithPhones,它将返回clientId。应该在createReferral和createSyContact中使用此clientId。
public Mono<ServerResponse> createClientProfile(ServerRequest request) {
final List<Long> clinetIdList = new ArrayList<>();
createClientWithPhones(request).subscribe(result -> {
clinetIdList.add(result.longValue());
createSyContact(request, result.longValue());
createReferral(request, result.longValue());
});
return ServerResponse
.created(URI.create(String.format(CLIENT_URI_FORMAT,
clinetIdList.get(0))))
.contentType(APPLICATION_JSON).build();
}
这种处理方式是否正确?
createClientProfile
方法中存在竞态条件。由于它是在组装时执行的,而不是作为反应链的一部分执行的,因此可能会在createClientWithPhones
完成之前调用ServerResponse
方法。使用此代码很可能会出现 IndexOutOfBounds 异常。 - Michael McFadyen