【发布时间】:2021-09-02 13:43:03
【问题描述】:
所以我想实现保存用户的功能
首先我检查用户是否存在
如果存在则抛出异常
否则保存用户
但是当我从服务层抛出异常时.flatMap(user -> Mono.error(new IllegalArgumentException("User Exists with email " + user.getEmail())))
@Service
@RequiredArgsConstructor
public class AppUserService {
private final AppUserRepository appUserRepository;
public Flux<AppUser> getAllUsers() {
return appUserRepository.findAll();
}
public Mono<AppUser> saveUser(AppUser appUser) {
return getUser(appUser.getEmail())
.flatMap(user -> Mono.error(new IllegalArgumentException("User Exists with email " + user.getEmail())))
.switchIfEmpty(Mono.defer(() -> appUserRepository.save(appUser))).cast(AppUser.class).log();
}
public Mono<AppUser> getUser(String email) {
return appUserRepository.findFirstByEmail(email);
}
}
如果我像 .onErrorResume(error -> ServerResponse.badRequest().bodyValue(error)) 那样处理它,则在控制器层中
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
public class AppUserController {
private final AppUserService appUserService;
private final PasswordEncoder encoder;
@GetMapping
public Flux<AppUser> getAllUsers(@RequestHeader("email") String email) {
return appUserService.getAllUsers();
}
@PostMapping
@CrossOrigin
public Mono<ResponseEntity<Object>> saveUser(@RequestBody Mono<AppUser> appUserMono) {
return appUserMono
.doOnSuccess(appUser -> appUser.setPassword(encoder.encode(appUser.getPassword())))
.subscribeOn(Schedulers.parallel())
.flatMap(appUserService::saveUser)
.flatMap(savedAppUser -> ResponseEntity.created(URI.create("/user/" + savedAppUser.getId())).build())
.onErrorResume(error -> Response entity.badRequest().bodyValue(error))
.log();
}
}
它在控制台上抛出一个错误
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.springframework.web.reactive.function.server.DefaultEntityResponseBuilder$DefaultEntityResponse and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
并向客户端返回 200
我做错了什么
阅读错误后,它似乎得到了一个空值
但是如果我在onErrorResume(error -> ..) 处调试流程,则错误变量有错误
不明白为什么它仍然抛出杰克逊错误
是不是因为杰克逊无法订阅 ServerResponse 或类似的东西
【问题讨论】:
-
你为什么打电话给
cast?异常表示某些内容很可能是空的。你在某处返回空的东西。由于您还没有发布完整的代码,我们不可能知道哪个函数返回空值。你确定数据库调用不返回空吗?还是存档? -
发布了整个代码,Cast 在那里是因为函数返回 Mono
并且 switchIfEmpty()在这种情况下返回Mono<Object>,因为在它之前调用了flatMap()。我检查了数据库它没有返回空它返回用户因此流进入服务层方法中的flatMap()并将Error返回给控制器,然后流进入方法onErrorResume() -
当某事返回
Mono<Object>时,这是一个确定的信号,表明链中较早的部分正在做一些错误的事情。您应该始终避免返回object,因为它是代码异味,类型系统可以帮助您,并且您会丢失类型信息。演员,直接告诉我你做的事情很糟糕。 -
是的,我同意,即使我也有一种感觉,这一定不是正确的方法。如果我想实现以下目标,你认为管道应该如何设计:当
saveUser()被调用时:getUser()将返回Mono<AppUser>所以我需要检查用户是否存在如果存在抛出异常如果它不返回任何数据或空保存用户? -
我做了一些实验,我认为您需要使用
switchIfEmpty和flatMap切换位置,以便它首先对空白部分做出反应,然后您是否运行 flatMap。
标签: java spring-webflux reactor webflux