我怎样才能使代码更具反应性;删除 if's,检查是否为空并进行中间日志记录
How can I make code more reactive; Remove if's, check for empty and do intermediate logging
我正在考虑如何以更具反应性的方式重写此代码(没有 if,在中间步骤中抛出异常等,以及记录中间结果的最佳实践)
return identityRepository.findByDeviceIdAndToken(
deviceId,
authToken
).doOnSuccess(identity -> {
if (identity == null) {
log.info(
"Pair Auth-Token: {} and Device-ID: {} not found",
authToken,
deviceId
);
}
})
.map(MyPrincipal::new)
.map(
principal -> {
if (!principal.isCredentialsNonExpired()) {
throw new CredentialsExpiredException();
}
return
new UsernamePasswordAuthenticationToken(
principal,
null,
Collections.emptyList()
)
;
}
)
.flatMap(this.authenticationManager::authenticate)
.map(SecurityContextImpl::new);
您可以这样更改地图逻辑:
return identityRepository.findByDeviceIdAndToken(
deviceId,
authToken
).doOnSuccess(identity -> {
if (identity == null) {
log.info(
"Pair Auth-Token: {} and Device-ID: {} not found",
authToken,
deviceId
);
}
})
.map(MyPrincipal::new)
.filter(principal -> principal.isCredentialsNonExpired())
.switchIfEmpty(Mono.error(new CredentialsExpiredException()))
.map(x -> new UsernamePasswordAuthenticationToken(
principal,
null,
Collections.emptyList()
)
)
.flatMap(this.authenticationManager::authenticate)
.map(SecurityContextImpl::new);
您可以使用 Optional 从代码中消除 if
条件。您的代码中总共有 2 个 if 条件。
让我们首先从 doOnSuccess
方法
中删除 if
.doOnSuccess(identity -> {
if (identity == null) {
log.info(
"Pair Auth-Token: {} and Device-ID: {} not found",
authToken,
deviceId
);
}
})
您可以使用 ifPresentOrElse 删除 if 条件。它是在 java 9:
中引入的
.doOnSuccess(identity -> Optional.ofNullable(identity)
.ifPresentOrElse(
val -> {},
() -> log.info(
"Pair Auth-Token: {} and Device-ID: {} not found",
authToken,
deviceId)
)
)
第二个if
条件在map
方法中
.map(principal -> {
if (!principal.isCredentialsNonExpired()) {
throw new CredentialsExpiredException();
}
return new UsernamePasswordAuthenticationToken(principal, null, Collections.emptyList());
})
在上面的代码中,您根据条件抛出一些异常。如果 Optional 由于过滤器而变为空,您可以使用 filter along with orElseThrow 抛出异常:
.map(principal -> Optional.of(new UsernamePasswordAuthenticationToken(principal, null, Collections.emptyList()))
.filter(token -> token.getPrincipal().isCredentialsNonExpired())
.orElseThrow(CredentialsExpiredException::new))
我正在考虑如何以更具反应性的方式重写此代码(没有 if,在中间步骤中抛出异常等,以及记录中间结果的最佳实践)
return identityRepository.findByDeviceIdAndToken(
deviceId,
authToken
).doOnSuccess(identity -> {
if (identity == null) {
log.info(
"Pair Auth-Token: {} and Device-ID: {} not found",
authToken,
deviceId
);
}
})
.map(MyPrincipal::new)
.map(
principal -> {
if (!principal.isCredentialsNonExpired()) {
throw new CredentialsExpiredException();
}
return
new UsernamePasswordAuthenticationToken(
principal,
null,
Collections.emptyList()
)
;
}
)
.flatMap(this.authenticationManager::authenticate)
.map(SecurityContextImpl::new);
您可以这样更改地图逻辑:
return identityRepository.findByDeviceIdAndToken(
deviceId,
authToken
).doOnSuccess(identity -> {
if (identity == null) {
log.info(
"Pair Auth-Token: {} and Device-ID: {} not found",
authToken,
deviceId
);
}
})
.map(MyPrincipal::new)
.filter(principal -> principal.isCredentialsNonExpired())
.switchIfEmpty(Mono.error(new CredentialsExpiredException()))
.map(x -> new UsernamePasswordAuthenticationToken(
principal,
null,
Collections.emptyList()
)
)
.flatMap(this.authenticationManager::authenticate)
.map(SecurityContextImpl::new);
您可以使用 Optional 从代码中消除 if
条件。您的代码中总共有 2 个 if 条件。
让我们首先从 doOnSuccess
方法
if
.doOnSuccess(identity -> {
if (identity == null) {
log.info(
"Pair Auth-Token: {} and Device-ID: {} not found",
authToken,
deviceId
);
}
})
您可以使用 ifPresentOrElse 删除 if 条件。它是在 java 9:
中引入的.doOnSuccess(identity -> Optional.ofNullable(identity)
.ifPresentOrElse(
val -> {},
() -> log.info(
"Pair Auth-Token: {} and Device-ID: {} not found",
authToken,
deviceId)
)
)
第二个if
条件在map
方法中
.map(principal -> {
if (!principal.isCredentialsNonExpired()) {
throw new CredentialsExpiredException();
}
return new UsernamePasswordAuthenticationToken(principal, null, Collections.emptyList());
})
在上面的代码中,您根据条件抛出一些异常。如果 Optional 由于过滤器而变为空,您可以使用 filter along with orElseThrow 抛出异常:
.map(principal -> Optional.of(new UsernamePasswordAuthenticationToken(principal, null, Collections.emptyList()))
.filter(token -> token.getPrincipal().isCredentialsNonExpired())
.orElseThrow(CredentialsExpiredException::new))