首页 > 解决方案 > Spring Web Flux 和 Reactor 中的 Map 与 FlatMap

问题描述

我一直在使用 Spring Boot 2.0.1 及其 Webflux 库开发一个示例响应式 Web api。我一直在看网上的例子来尝试构建它,但我被两件事难住了。以下是我的两个问题。

1)如何返回响应实体的通量,当我尝试时收到一条错误消息,指出只能返回单个响应实体。以下是我当前的代码。

@Service
public class MovieServiceImpl implements MovieService {

    @Autowired
    private MovieRepository movieRepository;

    @Override
    public Flux<Movie> list(){
        return movieRepository.findAll();
    }
}

@RestController
public class MovieRestController {

    @Autowired
    private MovieService movieService;

    @GetMapping(value = "/movies")
    public Flux<Movie> list() {

        return movieService.list();
    }
}

2)当我更新一个对象时,我使用 flatMap 来更新保存在 Mongo 中的对象,然后使用 Map 将其转换为响应实体。我的问题是为什么我在这里使用 flatMap 而不是 map?我从在线示例中得出此代码,但没有示例解释 flatMap 的使用。我想了解为什么在这里使用它。下面是代码。

@Service
public class MovieServiceImpl implements MovieService {

    @Autowired
    private MovieRepository movieRepository;

    @Override
    public Mono<Movie> update(String id, MovieRequest movieRequest) {

       return movieRepository.findById(id).flatMap(existingMovie -> {

           if(movieRequest.getDescription() != null){
               existingMovie.setDescription(movieRequest.getDescription());
           }
           if(movieRequest.getRating() != null){
               existingMovie.setRating(movieRequest.getRating());
           }
           if(movieRequest.getTitle() != null) {
               existingMovie.setTitle(movieRequest.getTitle());
           }

           return movieRepository.save(existingMovie);

       });
    }
}

@RestController
public class MovieRestController {

    @Autowired
    private MovieService movieService;

    @PutMapping("/movies/{movieId}")
    public Mono<ResponseEntity<Movie>> update(
            @PathVariable("movieId") final String movieId,
            @RequestBody final MovieRequest movieRequest) {

        return movieService.update(movieId, movieRequest)
                .map(m -> new ResponseEntity<>(m, HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));

    }
}

标签: spring-webflux

解决方案


  1. HTTP 请求的响应是唯一的。您所能做的就是发送一个FluxorMono作为响应的主体,并使用一个Content-Type标头让客户端知道它可以作为流application/stream+json或通常的application/json.

  2. 两者findById(id)movieRepository.save(existingMovie)返回Mono<Movie>。如果您映射它,Movie传递给映射的每个事件都将返回 a Mono<Movie>,因此 的串联findById().map(movieRepository.save())以 a 结尾Mono<Mono<Movie>>。当您使用平面地图时,您基本上是将地图中的所有发布者“合并”成一个Mono.


推荐阅读