[英].block() within reactive flow (Spring Webflux) for object that holds state
[英]Unable to return a request within webflux in reactive manner
這是我的代碼中的以下流程:用戶調用創建代理端點,包含代理名稱和布爾字段 ->
路由器函數接收調用,傳遞給處理程序 ->
處理程序將請求主體轉換為 Mono,將該單聲道傳遞給服務 ->
Service 將代理保存到 DB,在這個過程中生成一個 ID,然后創建一個包含 ID 的 Response 對象包裹在 Mono 中,將 Response 返回給 Handler。
這是我被卡住的部分。 保持反應式方法,我必須將 Agency 保存到 Db 並在 Mono 的“doOnNext() 部分中創建 ID。但是,我無法返回從 DB 獲得的 ID 以創建響應對象。
實現此目的的反應式方法是什么? 提前致謝!
public RouterFunction<ServerResponse> createAgency() {
return RouterFunctions
.route(POST("/agency").and(accept(MediaType.APPLICATION_JSON)), handler::createAgency);
}
@Component
@AllArgsConstructor
public class AgencyHandler {
private final AgencyServiceImpl service;
@NonNull
public Mono<ServerResponse> createAgency(ServerRequest request){
Mono<CreateAgencyRequest> agency = request.bodyToMono(CreateAgencyRequest.class);
Mono<CreateAgencyResponse> response = service.createAgency(agency);
return ServerResponse.created(URI.create("/agency"))
.contentType(MediaType.APPLICATION_JSON)
.body(response, CreateAgencyResponse.class);
}
}
@Service
@AllArgsConstructor
public class AgencyServiceImpl implements AgencyService {
private final AgencyRepository agencyRepository;
private final UuidGenerator uuidGenerator;
public Mono<CreateAgencyResponse> createAgency(Mono<CreateAgencyRequest> request) {
UUID id;
request.doOnNext(agency -> {
UUID agencyId = uuidGenerator.getUUID();
Mono<Agency> newAgency = Mono.just(
new Agency(
agencyId,
agency.getFields().getName()
));
//repository.save(newAgency)
//return Mono.just(new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString())));
});
// return request
return Mono.just(new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString())));
}
}
doOnNext
是副作用,你要找的是flatMap
return request.flatMap(agency -> {
final UUID agencyId = uuidGenerator.getUUID();
return repository.save(new Agency(agencyId, agency.getFields().getName()))
.thenReturn(agencyId);
}).flatMap(id -> ServerResponse.ok()
.bodyValue(new CreateAgencyResponseData(agencyId.toString()))
.build();
Wrote this without a compiler to check the code but yu should get the gist of it.
doOnNext
不是執行 I/O 綁定操作(例如數據庫訪問)的好選擇。 您應該改用flatmap
。 另外,請查看用於同步 1 對 1 轉換的map
運算符。
最終代碼應如下所示:
public Mono<CreateAgencyResponse> createAgency(Mono<CreateAgencyRequest> request) {
return request.map(req -> new Agency(uuidGenerator.getUUID(), req.getFields().getName()))
.flatMap(agency -> repository.save(agency))
.map(agency -> new CreateAgencyResponse(new CreateAgencyResponseData(agency.getAgencyId())));
}
像下面這樣的東西應該可以解決問題:
@Service
@AllArgsConstructor
public class AgencyServiceImpl implements AgencyService {
private final AgencyRepository agencyRepository;
private final UuidGenerator uuidGenerator;
public Mono<CreateAgencyResponse> createAgency(Mono<CreateAgencyRequest> request) {
UUID agencyId = uuidGenerator.getUUID();
return request.flatMap(createAgencyRequest -> {
Agency agency = new Agency(agencyId, agency.getFields().getName();
return repository.save(newAgency);
}).map(saved ->
new CreateAgencyResponse(new CreateAgencyResponseData(agencyId.toString()));
)
}
}
您將在flatMap
操作中創建Agency
並將其存儲在數據庫中。 我假設您的repository
也是響應式的,因此它也應該返回Mono
,因此是flatMap
操作。 之后,您只需要映射repository
返回的任何內容(您可能希望根據對數據庫的成功操作在此處設置一些邏輯)以創建CreateAgencyResponse
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.