如何在java中链接检查

如何在java中链接检查,java,refactoring,chaining,Java,Refactoring,Chaining,考虑下面这样一个类 public class MyClass { private Integer myField; private Result result; // more global variables public MyResult check(Integer myParameter) { init(myParameter); if (myField < 0) { result.setE

考虑下面这样一个类

public class MyClass {

    private Integer myField;
    private Result result;
    // more global variables

    public MyResult check(Integer myParameter) {
        init(myParameter);

        if (myField < 0) {
            result.setErrorMessage("My error message");
            return result;
        }

        // a lot more 'checks' like above where something may be written
        // to the error message and the result gets returned.
    }

    private void init(Integer myParameter) {
        result = new Result();
        result.setExistsAnnouncement(/*search a certain object via crudService with myParameter*/);
        // initialize other global variables including myField
    }

}
其思想是:当
检查
失败时,它的行为类似于
Optional.map()
,并返回类似于
Optional.EMPTY的内容(或者在本文中类似于
失败的内容)。当
检查
成功时,应继续进行下一次检查(返回
成功

您有这样做的经验吗?

您可以使用(或Bean验证标准的另一个实现)

使用无效参数实例化时引发异常的示例用户类。可以检查所有内置约束

和验证程序类:

import java.security.InvalidParameterException;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

public final class MyValidator {

    public static void validate(Object object) {

      ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
      Validator validator = factory.getValidator();

      Set<ConstraintViolation<Object>> constraintViolations = validator.validate( object );

      if (!constraintViolations.isEmpty()) {
          ConstraintViolation<Object> firstViolation = constraintViolations.iterator().next();

          throw new InvalidParameterException("not valid "
          + object.getClass()
          + " failed property ' " + firstViolation.getPropertyPath() + " ' "
          + " failure message ' " + firstViolation.getMessage() + " ' ");
      }
    }
}
import java.security.InvalidParameterException;
导入java.util.Set;
导入javax.validation.ConstraintViolation;
导入javax.validation.validation;
导入javax.validation.Validator;
导入javax.validation.ValidatorFactory;
公共最终类MyValidator{
公共静态无效验证(对象){
ValidatorFactory=Validation.buildDefaultValidatorFactory();
Validator Validator=factory.getValidator();
Set constraintViolations=validator.validate(对象);
如果(!constraintViolations.isEmpty()){
ConstraintViolation firstViolation=constraintViolations.iterator().next();
抛出新的InvalidParameterException(“无效”
+object.getClass()
+“失败的属性“”+firstViolation.getPropertyPath()+””
+“失败消息”“+firstViolation.getMessage()+””);
}
}
}
和信息:

java.security.InvalidParameterException:无效类 com.foo.bar.User失败属性“firstName”失败消息“可能不为null”

不要忘记在pom.xml中包含(如果使用Maven)


org.hibernate
休眠验证器
5.4.1.最终版本

当我们考虑验证时,它通常是一种复合模式。其大致描述如下:

如果这是有效的,那么做些什么

当您施加压力时,您希望将多个检查器链在一个链中,以在其所在区域执行验证,您可以实现一个责任链模式

考虑这一点:

您可以有一个
Result
对象,它可以包含关于失败的消息以及简单的true/false

您可以有一个
验证器
对象,它执行任何需要的验证,并返回
结果
的实例

public interface Result {  
    public boolean isOk();
    public String getMessage();
}

// We make it genric so that we can use it to validate
// any type of Object that we want.
public interface Validator<T> {
    public Result validate(T value);
}
就这样!现在,要实现您的检查程序:

public class Checker1 implements Validator<Integer> {
    /* Implementation */
}

public class CheckerN implements Validator<Integer> {
    /* Implementation */
}
公共类Checker1实现验证器{
/*实施*/
}
公共类CheckerN实现了验证器{
/*实施*/
}
现在是进行验证的时候了:

Validator<Integer> checkingRule = new Rule(new Checker1(), new CheckerN());
CompositeResult result = checkingRule.validate(yourParameter);
if (result.isOk()) 
    System.out.println("All validations passed");
else
    System.out.println(result.getFailedCount() + " validations failed");
Validator checkingRule=new规则(new Checker1(),new CheckerN());
CompositeResult结果=checkingRule.validate(您的参数);
if(result.isOk())
System.out.println(“所有验证通过”);
其他的
System.out.println(result.getFailedCount()+“验证失败”);
简单整洁


我已经上传了一个供你玩的链接。

我以前也做过同样的事情,但没有链接。我这样做的方式是1。)创建一个接口
Checkable
,其中包含一个方法
check()
,该方法需要抛出一些
checkfailedeexception
,以及该接口的一些具体实现。2.)在
MyClass
中创建一个
List
变量,
MyClass
中的
check()
迭代checkable的每个元素,并对其调用
check()
。3.)使用构造函数或setter方法初始化要执行的检查列表(我使用的是spring,所以我这样做了)。是的,这可能会起作用。但我认为有更好的解决办法。目前,我仍在尝试使用“尝试-失败-成功”模式,如此处所述:。区别在于:在链接中,他们这样做是为了例外。。。我正在使用这个Try Success Failure实现顺便说一句:如果您在编译时知道约束条件,您可以使用Hibernate验证器吗@aepure:检查不仅与数据库相关。@Chris311我喜欢你的实现。事实上,我也可以在我的应用程序中使用它。我是怎么想的,你想把支票串起来,对吗?您可以尝试做一些类似于
try
的事情,但我担心这会造成更多的开销和混乱,或者把事情弄得一团糟最糟糕的情况……非常好的解决方案!只有一个区别:所有验证器都被执行,而我希望在第一次检查失败后返回。但是你可以很容易地调整你的
验证
以满足我的要求。@Chris311你是对的。如果规则的任何组件失败,您可以抛出一个异常,但我太懒了,无法实现它。我宁愿使用
中断
public interface Result {  
    public boolean isOk();
    public String getMessage();
}

// We make it genric so that we can use it to validate
// any type of Object that we want.
public interface Validator<T> {
    public Result validate(T value);
}
public class Rule extends ArrayList<Validator> implements Validator {

    public Rule(Validator<?> ... chain) {
        addAll(Arrays.asList(chain));
    }

    public Object validate(Object target) {
        CompositeResult result = new CompositeResult(size());
        for (Validator rule : this) {
            Result tempResult = rule.validate(value);
            if (!tempResult.isOk())
                result.put(rule, tempResult);
        }
        return result;
    }
}

public class CompositeResult extends HashMap<Validator, Result> implements
        Result {

    private Integer appliedCount;

    public CompositeResult(Integer appliedCount) {
        this.appliedCount = appliedCount;
    }

    @Override
    public boolean isOk() {
        boolean isOk = true;
        for (Result r : values()) {
            isOk = r.isOk();
            if (!isOk)
                break;
        }
        return isOk;
    }

    @Override
    public String getMessage() {
        return toString();
    }

    public Integer failCount() {
        return size();
    }

    public Integer passCount() {
        return appliedCount - size();
    }

}
public class Checker1 implements Validator<Integer> {
    /* Implementation */
}

public class CheckerN implements Validator<Integer> {
    /* Implementation */
}
Validator<Integer> checkingRule = new Rule(new Checker1(), new CheckerN());
CompositeResult result = checkingRule.validate(yourParameter);
if (result.isOk()) 
    System.out.println("All validations passed");
else
    System.out.println(result.getFailedCount() + " validations failed");