我正在使用Spring WebFlux和Reactive Spring Data MongoDB实现一个简单的基于Movie的CRUD API。我想确保我的实现是正确的,并且我正在使用Flux和Mono来实现CRUD操作。我还想确保我正确处理任何错误或空值。我对这个编程范例和Spring WebFlux都很陌生,所以我不确定Controller和Service层实现的正确性,我想确保我遵守Spring WebFlux和Project Reactor的最佳实践。
@Repository
public interface MovieRepository extends ReactiveMongoRepository<Movie, String> {
Flux<Movie> findByRating(String rating);
}
public interface MovieService {
Flux<Movie> list();
Flux<Movie> findByRating(String rating);
Mono<Movie> update(String id, MovieRequest movieRequest);
Mono<Movie> create(Mono<MovieRequest> movieRequest);
Mono<Movie> read(String id);
Mono<Movie> delete(String id);
}
@Service
public class MovieServiceImpl implements MovieService {
@Autowired
private MovieRepository movieRepository;
@Override
public Flux<Movie> list(){
return movieRepository.findAll();
}
@Override
public Flux<Movie> findByRating(final String rating){
return movieRepository.findByRating(rating);
}
@Override
public Mono<Movie> update(String id, MovieRequest movieRequest) {
return movieRepository.findOne(id).map(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 existingMovie;
}).then(movieRepository::save);
}
@Override
public Mono<Movie> create(Mono<MovieRequest> movieRequest) {
return movieRequest.map(newMovie -> {
Movie movie = new Movie();
if(newMovie.getDescription() != null){
movie.setDescription(newMovie.getDescription());
}
if(newMovie.getRating() != null){
movie.setRating(newMovie.getRating());
}
if(newMovie.getTitle() != null) {
movie.setTitle(newMovie.getTitle());
}
return movie;
}).then(movieRepository::save);
}
@Override
public Mono<Movie> read(String id) {
return movieRepository.findOne(id);
}
@Override
public Mono<Movie> delete(String id) {
Mono<Movie> movie = movieRepository.findOne(id);
movieRepository.delete(id);
return movie;
}
}
@RestController
public class MovieRestController {
@Autowired
private MovieService movieService;
@GetMapping(value = "/movies")
public Flux<ResponseEntity<Movie>> list() {
return movieService.list().map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
@GetMapping(value = "/moviesByRating")
public Flux<ResponseEntity<Movie>> findByRating(
@RequestParam(value = "rating", required = false) final String rating) {
return movieService.findByRating(rating)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
@GetMapping("/movies/{movieId}")
public Mono<ResponseEntity<Movie>> read(
@PathVariable("movieId") final String movieId) {
return movieService.read(movieId)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
@DeleteMapping("/movies/{movieId}")
public Mono<ResponseEntity<Movie>> delete(
@PathVariable("movieId") final String movieId) {
return movieService.delete(movieId)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
@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));
}
@PostMapping("/movies")
public Mono<ResponseEntity<Movie>> create(
@RequestBody final Mono<MovieRequest> movieRequest) {
return movieService.create(movieRequest)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
}