检查 -->
我的模型看起来像这样。
@Document
public class PlanDetails {
@Id
private String id;
private String name;
private Double balance;
private Double internet;
private Date date;
--> //String of id's basically.
private List<String> members;
public PlanDetails(){}
public PlanDetails(String id, String name, Double balance, Double internet, Date date, List<String> members){
this.id = id;
this.name = name;
this.balance = balance;
this.internet = internet;
this.date = date;
this.members = members;
}
public String getId() {
return id;
}
/* Getter setters ommited for brevity */
这是我的处理程序类,用于处理我的功能端点。
package com.startelco.plandetailsapi.handler;
import com.startelco.plandetailsapi.model.PlanDetails;
import com.startelco.plandetailsapi.repository.PlanRepository;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import static org.springframework.http.MediaType.APPLICATION_JSON;
@Component
public class PlanDetailsHandler {
private PlanRepository repository;
public PlanDetailsHandler(PlanRepository repository){
this.repository = repository;
}
//Get All Users
public Mono<ServerResponse> getAllUsers(ServerRequest request){
Flux<PlanDetails> users = repository.findAll();
return ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(users,PlanDetails.class);
}
--> //Get User by ID
public Mono<ServerResponse> getUserDetails(ServerRequest request){
String id = request.pathVariable("id");
Mono<PlanDetails> userMono = repository.findById(id);
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
return userMono.flatMap(user ->
ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(BodyInserters.fromObject(user))
.switchIfEmpty(notFound)
);
}
//Create a user
public Mono<ServerResponse> saveUser(ServerRequest request){
Mono<PlanDetails> userMono = request.bodyToMono(PlanDetails.class);
return userMono.flatMap(user ->
ServerResponse.status(HttpStatus.CREATED)
.contentType(APPLICATION_JSON)
.body(repository.save(user),PlanDetails.class)
);
}
//Update user by ID
public Mono<ServerResponse> updateUser(ServerRequest request) {
String id = request.pathVariable("id");
Mono<PlanDetails> existingUserMono = this.repository.findById(id);
Mono<PlanDetails> userMono = request.bodyToMono(PlanDetails.class);
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
return userMono.zipWith(existingUserMono,
(user, existingUser) ->
new PlanDetails(existingUser.getId(), user.getName(), user.getBalance(), user.getInternet(),user.getDate(),user.getMembers())
)
.flatMap(user ->
ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(repository.save(user), PlanDetails.class)
).switchIfEmpty(notFound);
}
//Delete All Users
public Mono<ServerResponse> deleteAllUsers(ServerRequest request) {
return ServerResponse.ok()
.build(repository.deleteAll());
}
}
问题:通过重用之前编写的函数 getUserDetails.
来编写 getMemberDetails
的 Reactive 方法是什么?
Requirement.
所需功能:获取成员(member)详细信息功能。
public Mono<ServerResponse> getMemberDetails(ServerRequest request) {
--> //Pseudocode
String id = request.pathVariable("id");
Mono<PlanDetails> userMono = repository.findById(id);
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
if(userMono.member is not null){
int length = userMono.member.length
Flux<PlanDetails> memberFlux;
for(int i=0;i<length;i++){
Mono<PlanDetails> member = getUserDetails(id=userMono.member[i]);
memberFlux.add(member);
}
}else{
return ServerResponse.ok().build(memberFlux=null or empty array);
}
return ServerResponse.ok().build(memberFlux.flatmap);
}
期望的行为
{
"id": "5b42ecc11cde674475cab39a",
"name": "Alex Svirsky",
"balance": 140,
"internet": 20,
"date": 1531107095659,
"members": [
"5b42ecdd1cde674475cab39b",
"5b42ed421cde674475cab39c",
"5b42ed5d1cde674475cab39d"
]
}
我的路由中的 REST 调用定义为 http://localhost:8080/users/members/5b42ecc11cde674475cab39a
[ {
"id": "5b42ecdd1cde674475cab39b",
"name": "Bob Marley",
"balance": 120,
"internet": 9,
"date": 1531107095559,
"members": null
},
{
"id": "5b42ed421cde674475cab39c",
"name": "Charlie Sheen",
"balance": 10,
"internet": 9,
"date": 1531107095555,
"members": null
},
{
"id": "5b42ed5d1cde674475cab39d",
"name": "Dale Carnegie",
"balance": 100,
"internet": 9,
"date": 1531107055555,
"members": null
}
]
最佳答案
在我看来,第一种方法中没有太多可以重用的地方:因为这两种方法都返回一个完整的 ServerResponse
。 , 你不能创作原作。这仅仅是 repository.findById()
用一些样板将其转换为 ok
响应或 404
回应...
所以你真正需要的是一种编写getMemberDetails
的方法在对 repository.findById
的许多调用之上.如果我正确解释你的伪代码,你希望响应只是一个 Flux<PlanDetail>
原始“用户”下的所有“成员”(忽略有关所述原始用户的信息)?
您应该能够使用 flatMap
响应式地执行此操作:
public Mono<ServerResponse> getMemberDetails(ServerRequest request) {
String id = request.pathVariable("id");
Mono<PlanDetails> userMono = repository.findById(id);
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
return userMono
//transform from user mono to Flux of member details
.flatMap(user -> Flux.fromArray(user.member)) //if `member` is an Iterable use the following instead:
//.flatMapIterable(user -> user.member)
//now we have a Flux of member IDs, go get details
.flatMap(repository::findById)
//this will naturally ignore not found members
//if no member is found or array of IDs is empty, the main sequence is itself empty at this point
.switchIfEmpty(notFound);
}
此方法唯一需要注意的是,它不区分“未找到”(未找到原始用户)与“无内容”(用户没有可以找到的成员)。
关于java - 如何使用 Spring WebFlux Reactive 方式在处理函数中使用 Mono 和 Flux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51243415/