无法以反应方式 return webflux 中的请求
Unable to return a request within webflux in reactive manner
这是我的代码中的以下流程:
用户调用创建代理端点,包含代理名称和布尔字段 ->
路由器函数接收调用,传递给处理程序 ->
Handler 将请求主体转换为 Mono,将那个 Mono 传递给服务 ->
Service 将代理保存到 DB,在此过程中生成一个 ID,然后创建一个 Response 对象,其中包含用 Mono 包装的 ID,returns Response 返回给 Handler。
这是我卡住的部分。为了保持反应性方法,我必须将 Agency 保存到 Db 并在 Mono 的“doOnNext()”部分中创建 ID。但是,我无法 return 我从 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());
在没有编译器检查代码的情况下编写此代码,但您应该了解它的要点。
doOnNext
不是执行 I/O 绑定操作(例如数据库访问)的好选择。您应该改用 flatmap
。另外,请查看 map
用于同步、1 对 1 转换的运算符。
最终代码应如下所示:
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
也是反应性的,所以它也应该 return Mono
,因此 flatMap
操作。之后,您只需要映射任何 repository
returned(您可能希望在此处基于对数据库的成功操作有一些逻辑)来创建 CreateAgencyResponse
.
这是我的代码中的以下流程: 用户调用创建代理端点,包含代理名称和布尔字段 ->
路由器函数接收调用,传递给处理程序 ->
Handler 将请求主体转换为 Mono,将那个 Mono 传递给服务 ->
Service 将代理保存到 DB,在此过程中生成一个 ID,然后创建一个 Response 对象,其中包含用 Mono 包装的 ID,returns Response 返回给 Handler。
这是我卡住的部分。为了保持反应性方法,我必须将 Agency 保存到 Db 并在 Mono 的“doOnNext()”部分中创建 ID。但是,我无法 return 我从 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());
在没有编译器检查代码的情况下编写此代码,但您应该了解它的要点。
doOnNext
不是执行 I/O 绑定操作(例如数据库访问)的好选择。您应该改用 flatmap
。另外,请查看 map
用于同步、1 对 1 转换的运算符。
最终代码应如下所示:
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
也是反应性的,所以它也应该 return Mono
,因此 flatMap
操作。之后,您只需要映射任何 repository
returned(您可能希望在此处基于对数据库的成功操作有一些逻辑)来创建 CreateAgencyResponse
.