如何在ifPresent内部处理异常?

时间:2018-07-24 16:50:36

标签: java exception java-8 java-stream optional

在方法内部,需要一个条件来进行逻辑处理。我的IDE中显示未处理的异常警告消息。用try-catch包裹整个块不会使消息消失。

public void changePassword(String login, String currentClearTextPassword, String newPassword) {

    userRepository.findOneByLogin(login)
            .ifPresent(user -> {
                String currentEncryptedPassword = user.getUserSecret();
                String encryptedInputPassword = "";
                try {
                    encryptedInputPassword = authUtils.encrypt(currentClearTextPassword);
                } catch (Exception ex) {
                    System.err.println("Encryption exception: " + ex.getMessage());
                }
                if (!Objects.equals(encryptedInputPassword, currentEncryptedPassword)) {
                    throw new Exception("Invalid Password");  // <-- unhandled exception
                }
                String encryptedNewPassword = "";
                try {
                    encryptedNewPassword = authUtils.encrypt(newPassword);
                } catch (Exception ex) {
                    System.err.println("Encryption exception: " + ex.getMessage());
                }
                user.setUserSecret(encryptedNewPassword);
                userRepository.save(user);
                log.debug("Changed password for User: {}", user);
            });
}

如何处理此警告消息?

3 个答案:

答案 0 :(得分:3)

在流操作内部处理异常会产生一些开销,我想将操作分开并使其:

public void changePassword(String login, String currentClearTextPassword, String newPassword) throws Exception {
    //get the user in Optional
    Optional<User> check = userRepository.findOneByLogin(login);

    //if the user is present 'isPresent()'
    if(check.isPresent()){

        //get the user from the Optional and do your actions
        User user = check.get();

        String currentEncryptedPassword = user.getUserSecret();
        String encryptedInputPassword = "";
        try {
            encryptedInputPassword = authUtils.encrypt(currentClearTextPassword);
        } catch (Exception ex) {
            throw new Exception("Encryption exception: " + ex.getMessage());
        }
        if (!Objects.equals(encryptedInputPassword, currentEncryptedPassword)) {
            throw new Exception("Invalid Password");  // <-- unhandled exception
        }
        String encryptedNewPassword = "";
        try {
            encryptedNewPassword = authUtils.encrypt(newPassword);
        } catch (Exception ex) {
            throw new Exception("Encryption exception: " + ex.getMessage());
        }
        user.setUserSecret(encryptedNewPassword);
        userRepository.save(user);
        log.debug("Changed password for User: {}", user);
    }
}

除了抛出异常外,还应该抛出异常。

答案 1 :(得分:0)

就像@ louis-wasserman一样,您可以使用未经检查的异常。

所以不是

throw new Exception("Invalid Password");

使用:

throw new RuntimeException("Invalid Password"); // for example

注意:最好使用适合您的用例的自定义RuntimeException。

答案 2 :(得分:0)

对于一般情况,@ pari-ngang是正确的:在lambda表达式中,您无法在调用函数之外处理已检查的异常。在lambda中使用未经检查的结构或使用try构造。

但是,需要执行这两项操作可能表明结构不良。一个这样的征兆就是在lambda中包含大量代码。以下是针对您的具体情况的一些建议:

1 。为了简化@ ycf-l的答案,请反转逻辑,如果找不到则返回user

Optional<User> user = userRepository.findOneByLogin(login);
if (!user.isPresent()) {
    return;
}
// ... carry on as before outside of a lambda

2 。将获取用户与更改用户密码的逻辑分开(您仍然必须传递异常备份):

if (user.isPresent()) {
    changePassword(user.get(), currentClearTextPassword, newPassword);
}

3 。您还可以使用vavr之类的库来简化try / catch块:

String encryptedInputPassword = Try.of(() -> authUtils.encrypt(currentClearTextPassword))
    .onFailure(e -> System.err.println("Encryption exception: " + e.getMessage()))
    .orElse("");

4 。如果您愿意使用vavr,也可以解决更普遍的问题:

userRepository.findOneByLogin(login)
    .map(user -> Try.of(() -> {
        // Your change password stuff goes here.
        changePassword(user, currentClearTextPassword, newPassword);
        return null; // I don't currently know of any way of passing a runnable.
  }))
  // This pulls the exception out of the lambda function, satisfying the compiler.
  .orElseGet(() -> Try.success(null))
  .getOrElseThrow(Function.identity());

我还没有使用过vavr,因此无法告诉您这是否是最有效/最干净的vavr方法/用法,但是它将解决您的问题。