2017-03-13 29 views
1

新的Spring开发人员在这里。我已经搜索了SO和春季文档,但无法弄清楚这一点。Spring验证 - 避免重复约束消息

我试图使用Spring验证通过构造函数任何适用Validator实现适用于任意对象注入所有注册的验证,并通过他们呼吁迭代和supports()然后有条件validate()。这是有效的,除非它产生重复的验证消息,因为JSR-303约束注释经过两次验证 - 一次为jsr303Validator,再次为mvcValidator

我试过调用所有验证器,然后删除重复的错误,但ObjectError上的equals()实现不能按需要工作(它会使条目具有相同的错误代码和消息)。

验证程序实行:

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

摇篮依赖性:

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一起使用,而且我不知道如何防止这种情况。

+0

一些代码将有助于理解您的问题 – Jaiwo99

回答

0

难道这不该发生什么?

您有多个验证程序注册了该对象,因此当您遍历所有对象时,请求验证消息时,您将得到重复项,因为它们都相似。

+0

这可能是应该发生的事情,但这不是我想要发生的事情。这个问题可以重新表述为:如何避免在使用Spring Web时注册多个JSR303验证器?我没有明确注册验证器,所以我不确定为什么有两个JSR303验证器或如何避免这种情况。 – Eric

+0

这很公平。你是否自动连线这些验证器?他们有不同的目的。我相信mvc会允许将表单绑定到消息上。你可以放弃其中一个验证器,但他们可能在将来做不同的事情(如果有人添加了一个自定义的)。 – TheNorthWes

+0

我没有明确自动装配验证器。我想只包括'org.springframework.boot:spring-boot-starter-web'注册MVC验证器。我想避免使用硬编码逻辑来排除MVC验证器(例如按类名称),因为您指出这看起来很脆弱。我正在寻找一种方法来控制注入或至少运行 - 基本上我需要标准的JSR303验证器('LocalValidatorFactoryBean')和任何特定于应用程序的自定义验证器。我只是不确定如何过滤注入的验证器列表(或选择更好的方法)。 – Eric