Java 业务逻辑验证模式&;忠告
我的应用程序中有两层验证。首先是由bean验证API执行的实体验证(例如必填字段)。 第二个层次是业务逻辑验证。例如,用户有一个帖子。只有当用户是此帖子的创建者且帖子评级<50时,才能删除帖子。所以我必须这样做:Java 业务逻辑验证模式&;忠告,java,spring,validation,design-patterns,Java,Spring,Validation,Design Patterns,我的应用程序中有两层验证。首先是由bean验证API执行的实体验证(例如必填字段)。 第二个层次是业务逻辑验证。例如,用户有一个帖子。只有当用户是此帖子的创建者且帖子评级
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")
if(post.getCreator().equals(session.getUser())){
if(post.getRating()<50){
postRepository.delete(post);
}其他错误。添加(400,“不能删除评级为50或更高的帖子”)
}else错误添加(400,“您应该是帖子的所有者”)
我不喜欢这种方式,因为这种条件被重用,我必须复制代码。此外,如果条件数大于5左右,那么阅读和理解代码就变得不真实
此外,标准Spring验证器不会有很大帮助,因为我必须在不同的操作上对一个实体进行不同的验证(例如删除和更新)
因此,我正在寻找一种更聪明的方法(可能是模式),如果有人能给我一个提示,我将非常感激
提前感谢 您可以使用
可以将每个条件建模为一个函数,该函数接受post和会话上下文,并可能返回错误:
Post -> Session -> Optional<String>
在我看来,战略模式是解决方案。 我将给你一个非常简单的例子。假设我们有两种信用卡,维萨卡和万事达卡。两张卡执行支付操作的逻辑相同,但卡号验证不同。因此,通过在工作流中传递VisaStrategy对象,除了在每个已定义的策略类中进行的卡号验证之外,执行与传递MastercardStrategy相同的逻辑和操作,因此代码中根本没有任何“if-else”内容。每个策略类现在只负责一种类型的卡验证。
如果您寻求灵活且易于维护的代码结构,请使用策略设计模式。如果验证方法的参数因条件而异,该怎么办?假设Visa卡号是一个整数,也有一个4位代码,但master卡号是一个16位数字?
@FunctionalInterface
public interface ValidationCondition {
Optional<String> validate(final Post post, final Session session);
}
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");
}
}
final List<ValidationCondition> conditions = new ArrayList<>();
conditions.add(new CreatorValidation());
conditions.add(new ScoreValidation());
// etc.
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());
}
}
final ValidationCondition condition = (post, session) -> {
// Custom logic
});