WebFlux:为什么需要在CRUD中使用flatMap

问题描述 投票:0回答:1

我在Internet上找到了示例,但这并不能完全理解我。 使用WebFlux时的标准CRUD。

路由器:

@Configuration
public class PersonRouter {

    @Bean
    public RouterFunction<ServerResponse> route(PersonHandler handler) {
        return RouterFunctions
                .route(GET("/getAllPersons").and(accept(MediaType.APPLICATION_JSON)), handler::findAll)
                .andRoute(GET("/getPerson/{id}").and(accept(MediaType.APPLICATION_STREAM_JSON)), handler::findById)
                .andRoute(POST("/createPerson").and(accept(MediaType.APPLICATION_JSON)), handler::save)
                .andRoute(DELETE("/deletePerson/{id}").and(accept(MediaType.APPLICATION_JSON)), handler::delete);
    }

}

Handler:

@Component
public class PersonHandler {

    private final PersonService personService;

    public PersonHandler(PersonService personService) {
        this.personService = personService;
    }

    public Mono<ServerResponse> findById(ServerRequest request) {
        String id = request.pathVariable("id");
        return ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(personService.getById(id), Person.class);
    }

    public Mono<ServerResponse> findAll(ServerRequest request) {
        return ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(personService.getAll(), Person.class);
    }

    public Mono<ServerResponse> save(ServerRequest request) {
        final Mono<Person> person = request.bodyToMono(Person.class);
        return ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(fromPublisher(person.flatMap(personService::save), Person.class));
    }

    public Mono<ServerResponse> delete(ServerRequest request) {
        String id = request.pathVariable("id");
        return ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(personService.delete(id), Void.class);
    }

}

存储库:

@Repository
public interface PersonRepository extends ReactiveMongoRepository<Person, String> {
}

服务:

@Service
@Transactional
@AllArgsConstructor
public class PersonService {

    private final PersonRepository personRepository;

    public Flux<Person> getAll() {
        return personRepository.findAll().switchIfEmpty(Flux.empty());
    }

    public Mono<Person> getById(final String id) {
        return personRepository.findById(id);
    }

    public Mono update(final String id, final Person person) {
        return personRepository.save(person);
    }

    public Mono save(final Person person) {
        return personRepository.save(person);
    }

    public Mono delete(final String id) {
        final Mono<Person> dbPerson = getById(id);
        if (Objects.isNull(dbPerson)) {
            return Mono.empty();
        }
        return getById(id).switchIfEmpty(Mono.empty()).filter(Objects::nonNull).flatMap(personToBeDeleted -> personRepository
                .delete(personToBeDeleted).then(Mono.just(personToBeDeleted)));
    }
}

我了解saveupdate方法之外的所有内容。我不明白为什么在这种情况下使用flatMap。为什么会这样,以及如何在Handler中编写update方法的实现。

更新

让我们看看处理程序中的方法save() >>

public Mono<ServerResponse> save(ServerRequest request) {
        final Mono<Person> person = request.bodyToMono(Person.class);
        return ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(fromPublisher(person.flatMap(personService::save), Person.class));
    }

我认为事实是我们已经收到了:

final Mono<Person> person = request.bodyToMono(Person.class);

然后我们做:

personService::save

结果,我们得到Mono >

flatMap类似于map,不同之处在于,如果[lambda]返回值本身包含在Publisher<T>中,则它将解压缩给定的lambda返回值。在我们的例子中,personService.save(T)方法返回Mono<T>。如果我们使用地图而不是flatMap(T),那么当我们真正想要的是Mono< Mono< T>>时,我们将拥有一个Mono<T>。我们可以使用flatMap彻底解决此问题。

我是对还是这个说法错了?

我在Internet上找到了示例,但这并不能完全理解我。使用WebFlux时使用标准CRUD。路由器:@Configuration公共类PersonRouter {@Bean公共...

crud spring-webflux project-reactor reactor spring5
1个回答
1
投票

为什么需要flatMap。

© www.soinside.com 2019 - 2024. All rights reserved.