Spring Web Flux和Reactor中的Map与FlatMap

Son*_*oku 0 spring-webflux

我一直在使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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));

    }
}
Run Code Online (Sandbox Code Playgroud)

Vik*_*ash 8

地图 :

@PutMapping(path="/update/{id}", consumes=MediaType.APPLICATION_JSON_VALUE)
public Mono<Account> update(@PathVariable Long id, @RequestBody Account account) {
    Mono<Account> accFound = accountRepository.findById(id);
    return accFound.map(acc -> {
        acc.setAccountBalance(account.getAccountBalance());
        return accountRepository.save(acc).block();
        });

}
Run Code Online (Sandbox Code Playgroud)

map将 a 添加Mono到内部accountRepository.save(acc)返回的任何内容,注意这里返回 a Mono,如果我不添加block(),则该方法update最终返回Mono<Mono<Account>>- 在这种情况下编译错误。

平面地图:

@PutMapping(path="/update/{id}", consumes=MediaType.APPLICATION_JSON_VALUE)
public Mono<Account> update(@PathVariable Long id, @RequestBody Account account) {
    Mono<Account> accFound = accountRepository.findById(id);
    return accFound.flatMap(acc -> {
        acc.setAccountBalance(account.getAccountBalance());
        return accountRepository.save(acc);
        });

}
Run Code Online (Sandbox Code Playgroud)

flatMap 简单地返回里面返回的任何内容。

希望它有助于以非常基本的方式理解它


dme*_*ezg 6

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

  2. 双方findById(id)movieRepository.save(existingMovie)Mono<Movie>。如果您将其映射,则Movie传递给该映射的每个事件都将返回,Mono<Movie>因此以findById().map(movieRepository.save())结束的串联Mono<Mono<Movie>>。平面地图绘制时,基本上是将地图上的所有发布者“合并”为一个Mono