首页 > 解决方案 > 有没有办法简化该源代码?

问题描述

我目前正在使用 Spring Boot 实现公告板 API。我将向您展示的源代码场景是关于公告板或评论修改,

两者都需要在修改前在评论或公告板输入时提交密码。

所以,我只是使用'isBoard'作为输入:隐藏值来执行'boardRepository'中的'findById'并将其与passwordEncoder的匹配函数进行比较,然后更新布尔值。

但是,下面的代码显示重复并使用了相同的逻辑。有没有办法让这更简单?

 @Transactional
public boolean tryToUpdateArticleOrReply(Long id, String password, boolean isBoard) throws ApiException {
    AtomicBoolean result = new AtomicBoolean(false);

    if(isBoard) {
         boardRepository.findById(id).ifPresent(
                board -> {
                    result.compareAndSet(passwordEncoder.matches(board.getUserPass(), password), true);
                }
         );
    } else {
        replyRepository.findById(id).ifPresent(
                reply -> {
                    result.compareAndSet(passwordEncoder.matches(reply.getUserPass(), password), true);
                }
        );
    }
    if(result.get())
      return result.get();

    throw new ApiException("INVALID_USER_PASS", "you submitted invaild password.", new ApiExceptionData().add("user_pass", password));
}

标签: javaspringspring-boot

解决方案


如果您的findByIdandgetUserPass方法来自接口(并且该findById方法返回getUserPass来自的接口),那么您可以简单地执行以下操作:

private boolean check(FindByIdInterface repository,
                      Long id,
                      String password) {
    return repository.findById(id)
            .map(result -> 
                passwordEncoder.matches(
                    result.getUserPass(), password))
            .orElse(false); 
}

然后只需在您根据变量 选择repository要传递的位置调用它。isBoardisBoard ? boardRepository : replyRepository


如果它们不是来自共享接口,那么您可以有效地“假装”它们使用 java 中的一些功能接口。

/* R = repository type, T = return type of 'findById' */
private <R, T> check(Function<R, Optional<T>> getByIdMapper,
                     Function<T, String> getUserPassMapper,
                     R repository,
                     Long id,
                     String password) {
    return getByIdMapper.apply(repository)
            .map(result ->
                passwordEncoder.matches(
                    getUserPassMapper.apply(result),
                    password))
            .orElse(false);
}

然后用类似这样的方式调用它:

if (isBoard) {
    return check(BoardRepository::getById,
                 Board::getUserPass,
                 boardRepository, id, password);
} else {
    // ...
}

请注意,在这两种情况下都不是AtomicBoolean必需的。


推荐阅读