我想验证一个名为Person
的类。我可以这样写:
class Person {
...
public boolean isValid() {
return (name != null && age > 0);
}
}
但是,在我的表示层中,我想向用户显示验证失败原因的具体原因。
我提出的解决方案是:
isValid()
内抛出异常isValid()
返回PersonValidationError
枚举而不是布尔值我想知道处理这个的最佳方法是什么。另外,Java标准库如何处理这种情况?
答案 0 :(得分:2)
我不知道你在用什么。我习惯了Spring MVC项目。 在这些上,您可以使用JSR-303验证器,它将使用对象上的所有错误填充ObjectErros对象。
如果您使用的是spring,请尝试寻找SmartValidator。注入后,您可以执行以下操作:
BeanPropertyErrors br = new BeanPropertyErros();
validator.validate(object,br);
如果您没有使用Spring,请尝试寻找JSR-303实现。
有了它,你可以在要验证的类的字段上使用@ NotEmpty,@ NotNull,@ Min,@ Length。
答案 1 :(得分:1)
我提出的建议如下:
class Person {
...
private boolean isValidated = false;
private ArrayList<String> validationErrors = new ArrayList<String>();
private void validate()
{
validationErrors.clear();
if (name == null)
validationErrors.add("Incorrect name");
if (age < 0)
validationErrors.add("Incorrect age");
isValidated = true;
}
public boolean isValid()
{
if (!isValidated)
validate();
return (validationErrors.size()==0);
}
public ArrayList<String> getValidationErors()
{
if (!isValidated)
validate();
return validationErrors;
}
答案 2 :(得分:1)
在提出我的解决方案之前的几点:
例外情况应该用于或多或少的例外条件。 根据您的说法,用户提交的内容并不少见 错误的数据。
当您的Person
班级增长时,您将添加越来越多必须满足的条件才能使其生效。
除了例外,您一次只能显示一个错误,如果提交的数据有多个错误怎么办?
将验证方法放入Person
课程似乎不对。例如,如果您希望在应用中的不同位置使用不同的验证政策,该怎么办?
所以,我会让你的Person类免于验证逻辑:
class Person {
final String name;
final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
然后实现一些带人并且验证它的类。我们的想法是拥有不同的验证器,每个验证器都有自己的验证规则和自己的验证消息。 enum
很高兴实现这一目标:
enum Validator {
NOT_NULL_NAME("Name must not be null") {
@Override
public boolean validate(Person person) {
return person.name != null;
}
},
AGE_GREATER_THAN_ZERO("Age must be greater than zero") {
@Override
public boolean validate(Person person) {
return person.age > 0;
}
};
final String errorMessage;
private Validator(String errorMessage) {
this.errorMessage = errorMessage;
}
public abstract boolean validate(Person person);
}
看看用不同的消息添加一些新条件有多容易?只是另一个枚举实例。
现在创建一个验证人员的课程。它只是遍历所有验证器并收集错误消息。
class PersonValidator {
private final List<String> errors = new ArrayList<String>();
public PersonValidator(Person person) {
for (Validator validator : Validator.values()) {
if (!validator.validate(person)) {
errors.add(validator.errorMessage);
}
}
}
public boolean isValid() {
return errors.isEmpty();
}
public Collection<String> getErrors() {
return errors;
}
}
如何使用它的示例:
public static void main(String... args) {
Person[] people = { new Person(null, 0),
new Person(null, 42),
new Person("Joe", 0),
new Person("Joe", 42) };
for (int i = 0; i < people.length; i++) {
PersonValidator validator = new PersonValidator(people[i]);
System.out.println(String.format("Person no %s is %s valid. %s",
i,
validator.isValid() ? "" : "not",
Joiner.on(", ").join(validator.getErrors())));
}
}
以上版画:
Person no 0 is not valid. Name must not be null, Age must be greater than zero
Person no 1 is not valid. Name must not be null
Person no 2 is not valid. Age must be greater than zero
Person no 3 is valid.
非常整洁,呵呵?
答案 3 :(得分:0)
我现在已经解决了以下问题:
class Person {
...
public void validate() throws ValidationException {
if(name == null) {
throw ValidationException("Name cannot be null");
}
if(age < 0) {
throw ValidationException("Age cannot be less than 0");
}
}
}
然后在我的表示层中,我可以执行以下操作:
try {
myPerson.validate();
} catch(ValidationException e) {
errorMessage = "Invalid person: " + e.getMessage();
}