业务逻辑验证模式和建议

Rah*_*hul 9 java validation spring design-patterns

我的应用程序中有两层验证.首先是由bean验证API执行的实体验证(例如必填字段).第二级是业务逻辑验证.例如,用户有一个帖子.用户可以删除帖子,只有他是这篇文章的创建者并且评分<50.所以我必须做这样的事情:

if (post.getCreator().equals(session.getUser())) {
  if (post.getRating() < 50) {
    postRepository.delete(post);
  } else errors.add(400, "Cant delete post with rating 50 or higher")
} else errors add (400, "You should be owner of the post")
Run Code Online (Sandbox Code Playgroud)

我不喜欢这种方式,因为这个条件被重用,我不得不重复代码.此外,如果条件数大于5,则读取和理解代码变得不真实.

此外,标准的Spring Validator不会非常有用,因为我必须为不同的操作(例如删除和更新)为一个实体制作不同的验证.

所以我正在寻找一种更聪明的方式(模式可能),如果有人能给我一个提示,我将非常感激.

预先感谢!

sdg*_*sdh 15

您可以使用策略模式.

每个条件都可以建模为一个函数,它接收一个帖子和一个会话,并可能返回一个错误:

Post -> PostContext -> Optional<String> 
Run Code Online (Sandbox Code Playgroud)

您可以使用界面表示:

@FunctionalInterface
public interface ValidationCondition {

    Optional<String> validate(final Post post, final Session session);
}
Run Code Online (Sandbox Code Playgroud)

例如:

public class CreatorValidation implements ValidationCondition {

    public Optional<String> validate(final Post post, final Session session) {
        if (post.getCreator().equals(session.getUser()) {
            return Optional.empty();
        }
        return Optional.of("You should be the owner of the post");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以将每个验证存储在列表中:

final List<ValidationCondition> conditions = new ArrayList<>();

conditions.add(new CreatorValidation());
conditions.add(new ScoreValidation());
// etc.
Run Code Online (Sandbox Code Playgroud)

使用该列表,可以批量应用验证:

final List<String> errors = new ArrayList<>();

for (final ValidationCondition condition : conditions) {
    final Optional<String> error = condition.validate(post, session);
    if (error.isPresent()) {
        errors.add(error.get());
    }
}
Run Code Online (Sandbox Code Playgroud)

使用Java 8 lambdas,您可以声明这些内联:

final ValidationCondition condition = (post, session) -> {
    // Custom logic
});
Run Code Online (Sandbox Code Playgroud)