我应该更喜欢 `ifPresent` 方法而不是 `isPresent` 方法吗?

Should I prefer the `ifPresent` method to the `isPresent` one?

我有使用后者的代码:

Optional<String> subject = Optional.ofNullable(claims.get().getSubject());
if (subject.isPresent()) {
  UserDetails userDetails = userDetailsService.loadUserByUsername(subject.get());
  UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails,
      null, userDetails.getAuthorities());
  authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
  logger.debug("Security - The request authenticated fine from the JWT Access token");
  return authentication;
} else {
  throw new BadCredentialsException("The authentication token " + optToken + " did not contain a subject.");
}

我正在尝试使用 ifPresent 方法重构它。

我应该在功能方法调用之前进行 userDetailsService.loadUserByUsername 服务调用吗?如果是这样,怎么办?如何 return 类型不同于功能方法类型的对象?

我在 Java 12.

在这种情况下,您可以使用 orElseThrow,如果值不存在则抛出异常:

String subjectValue = subject.orElseThrow(() ->
    new BadCredentialsException("The authentication token " + optToken + " did not contain a subject."));
...

使用map方法转换Optional的值。 改造后,可以使用orElseThrow方法解包Optional,如果为空则抛出异常。

像这样:

return Optional.ofNullable(claims.get().getSubject())
               .map(userDetailsService::loadUserByUsername)
               .map(userDetails -> {
                   UsernamePasswordAuthenticationToken authentication = 
                       new UsernamePasswordAuthenticationToken(
                           userDetails, null, userDetails.getAuthorities());
                   authentication.setDetails(
                       new WebAuthenticationDetailsSource().buildDetails(request));
                   return authentication;
               })
               .orElseThrow(() -> new BadCredentialsException(
                  "The authentication token " + optToken + " did not contain a subject."));

但是,在您的特定情况下,完全不使用 Optional 可能更简单。您可以立即检查 null。

String subject = claims.get().getSubject();
if (subject == null) {
    throw new BadCredentialsException(
        "The authentication token " + optToken + " did not contain a subject.");
}

UsernamePasswordAuthenticationToken authentication = ... ;

如果你真的想使用 ifPresent 你可以做类似

subject.ifPresent(s -> {
     UserDetails userDetails = loadUserByUsername(s);
     ...
});

但既然你要抛出一个缺失的主题,为什么不简单地做

String subject = Optional.ofNullable(claims.get().getSubject())
        .orElseThrow(() -> new BadCredentialsException(...));
UserDetails userDetails = loadUserByUsername(subject);
...