Spring验证 - 避免重复的约束消息

时间:2017-03-13 18:05:08

标签: java spring validation

这里有新的Spring开发人员。我搜索了SO和春季文档,但无法解决这个问题。

我正在尝试使用Spring Validation将任何适用的Validator实现应用于任意对象,方法是注入所有已注册的验证器,并通过调用supports()然后有条件地validate()进行迭代。这有效,除了它产生重复的验证消息,因为JSR-303约束注释被验证两次 - 一次由jsr303Validator验证,再由mvcValidator验证。

我尝试调用所有验证器并在之后删除重复的错误,但equals()上的ObjectError实现无法正常工作(它会使条目具有相同的错误代码和消息)。

验证器实施:

import org.springframework.validation.BindException;
import org.springframework.validation.Validator;

@Service
class ObjectValidatorImpl {
    private final Validator[] validators;

    public ObjectValidatorImpl(Validator[] validators) {
        this.validators = validators;
    }

    public void validate(Object obj) throws BindException {
        // Container for holding any validation errors that are found
        BindException errors = new BindException(obj, obj.getClass().getName());

        for (Validator validator : validators) {
            if (validator.supports(obj.getClass())) {
                validator.validate(obj, errors);
            }
        }

        if (errors.hasErrors()) {
            throw errors;
        }
    }
}

显示错误的示例程序:

@SpringBootApplication
public class ValidationTestApplication implements CommandLineRunner {

    @Autowired
    private ObjectValidator objectValidator;

    public static void main(String[] args) {
        SpringApplication.run(ValidationTestApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        try {
            objectValidator.validate(new TestObject());
        }
        catch (BindException ex) {
            System.out.println(ex);
        }
    }
}

class TestObject {
    @NotEmpty
    String name;
}

错误输出示例:

org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'validationtest.TestObject' on field 'name': rejected value [null]; codes [NotEmpty.validationtest.TestObject.name,NotEmpty.name,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [validationtest.TestObject.name,name]; arguments []; default message [name]]; default message [may not be empty]
Field error in object 'validationtest.TestObject' on field 'name': rejected value [null]; codes [NotEmpty.validationtest.TestObject.name,NotEmpty.name,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [validationtest.TestObject.name,name]; arguments []; default message [name]]; default message [may not be empty]

请注意jsr303ValidatormvcValidator报告两次“名称不能为空”错误。

Gradle依赖项:

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-validation')
    compile('org.springframework.boot:spring-boot-starter-web')
    runtime("com.h2database:h2")
}

解决此类情况的正确(最弹性?)方法是什么?感觉它是一个类路径配置问题,我应该避免在同一个项目中同时使用两个验证器,但是这个代码位于一个共享库中,可能与Spring Web MVC一起使用,也可能不使用,我不知道如何防止这种情况

1 个答案:

答案 0 :(得分:0)

这不是应该发生的事吗?

您为该对象注册了多个验证器,因此当您遍历所有验证器并请求验证消息时,您将获得重复,因为它们都是相似的。