2016-09-15 103 views
0

我使用Spring Boot 1.3.5和Rest Controllers並且一切正常。我正在使用Spring的官方文檔(JSR-303 Bean Validation API和Spring的驗證器界面,我試過並面臨相同的問題)的驗證示例技術,驗證正在工作,但我無法配置自定義消息。使用Spring的驗證器界面進行Bean驗證的自定義消息

我配置了一個messages.properties文件,我可以很好地訪問這個文件上的消息。但是,這個驗證似乎不能讀取或訪問我的消息源(messages.properties),通過spring啓動自動配置。

我可以通過@Autowired(在代碼中有註釋)直接從控制器中注入的消息源對象訪問消息。但是,Spring的驗證器接口或JSR-303 Bean驗證的綁定結果似乎無法訪問MessageSource中加載的messages.properties。我的結果是,我的錯誤有代碼,但沒有默認消息。

這裏是我的應用程序類:

@SpringBootApplication 
@ImportResource({ "classpath:security/cas-context.xml", "classpath:security/cas-integration.xml", 
    "classpath:security/security.xml" }) 
@EnableAutoConfiguration(exclude = VelocityAutoConfiguration.class) // http://stackoverflow.com/questions/32067759/spring-boot-starter-cache-velocity-is-missing 

public class Application extends SpringBootServletInitializer { 

@Override 
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 
    return application.sources(Application.class); 
} 

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

@Bean 
public ServletRegistrationBean cxfServlet() { 
    return new ServletRegistrationBean(new CXFServlet(), "/services/*"); 
} 

@Bean(name = Bus.DEFAULT_BUS_ID) 
public SpringBus springBus() { 
    return new SpringBus(); 
} 

@Bean 
public Nfse nfseService() { 
    return new NfseImpl(); 
} 

@Bean 
public Endpoint endpoint() { 
    EndpointImpl endpoint = new EndpointImpl(springBus(), nfseService()); 
    endpoint.publish("/nfseSOAP"); 
    return endpoint; 
} 

}

這裏是我的豆:

public class Protocolo { 

private Long id; 

@NotNull 
@Min(1) 
@Max(1) 
private String protocolo; 

private StatusProtocoloEnum status; 

public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

public String getProtocolo() { 
    return protocolo; 
} 

public void setProtocolo(String protocolo) { 
    this.protocolo = protocolo; 
} 

public StatusProtocoloEnum getStatus() { 
    return status; 
} 

public void setStatus(StatusProtocoloEnum status) { 
    this.status = status; 
} 

} 

這裏是我的休息控制器:

@RestController 
public class ProtocoloController { 

@Autowired 
private MessageSource messageSource; 

@Autowired 
private ProtocoloDAO protocoloDAO; 

@RequestMapping(value = "/prot", method = RequestMethod.POST) 
public void testar(@Valid @RequestBody Protocolo p) { 
    Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
    System.out.println(auth.getAuthorities()); 
    System.out.println(messageSource.getMessage("protocolo.tamanho", null, null)); 
// IN THIS PART I'M ABLE TO PRINT THE MESSAGE IF VALIDATION IS DISABLED 
    System.out.println(p.getProtocolo()); 
} 

}

因此,此代碼工作正常,並且該方法未被調用,因爲我用無效的Protocolo調用該方法。然而,我的angularJS客戶端收到錯誤代碼填充的響應,但所有默認消息都是空的,因爲驗證沒有看到我加載的messages.properties。

有沒有辦法讓我的Spring驗證接口或JSR-303驗證合併加載的message.properties(messagesource)在春季啓動?我怎樣才能糾正這一點?如果有必要,我也可以粘貼Spring Validation接口的代碼示例。

非常感謝,

Tarcísio。

TEST CODE:

@RestController 
public class ProtocoloController { 

@Autowired 
private MessageSource messageSource; 

@Autowired 
private ProtocoloDAO protocoloDAO; 

@RequestMapping(value = "/prot", method = RequestMethod.POST) 
public void testar(@Valid @RequestBody Protocolo p, BindingResult bindingResult) { 
    System.out.println(messageSource.getMessage("Min.protocolo.protocolo", null, null)); 
    if (bindingResult.hasErrors()) { 
       System.out.println(bindingResult.getFieldError().getDefaultMessage()); 
System.out.println(bindingResult.getFieldError().getCode()); 
    } 
    System.out.println(p.getProtocolo()); 
} 

}

回答

1

在春季啓動一個應用的MessageSource配置了MessageSourceAutoConfiguration和你不需要自動裝配它。對於jsr303,請在messages.properties文件中創建適當的鍵值對。對於「protocolo」字段,您應該在屬性文件中具有以下值。

NotNull.protocolo.protocolo=Field cannot be left blank 
Min.protocolo.protocolo=Minimum value must be {1} 

您也可以在代碼中檢查屬性文件中的消息,如下所示。

public void testar(@Valid @RequestBody Protocolo p,BindingResult bindingResult) { 
if(bindingResult.hasErrors()) { 
    System.out.println(bindingResult.getFieldError().getDefaultMessage()); 
    } 
} 
+0

我已經嘗試過了,也沒有工作。我做了autowire只是爲了測試,如果我可以直接從控制器使用autowired messagessource獲取消息,這是可能的。只有通過JSR303執行的驗證,我無法獲得消息。我在客戶端收到您發佈的確切密鑰:Min.protocolo.protocolo。但是,消息雖然在messages.propeties中指定,但是爲空。我錯過了一些配置,它將驗證JSR303或彈簧驗證界面與spring啓動配置的消息源相連接。 –

+0

我編輯了我的答案併爲bindingResult添加了一些代碼。你可以使用它來檢查嗎? – abaghel

+0

非常感謝!我使用您建議的代碼編輯了我的帖子。爲了測試,我還保留了自動裝配的消息源。結果是使用springboot和控制器中自動裝入的消息源打印的消息正是我在message.properties中自定義的消息:Min.protocolo.protocolo = my test。但是,在綁定結果中打印的消息是spring -JSR @Min的默認消息,也就是說,我使用默認消息打印的代碼消息與我通過自動裝入的消息源成功打印的消息相同。 –

4

編輯: Spring Boot 1.5中的已知錯誤。3看https://github.com/spring-projects/spring-boot/issues/8979

春季啓動以來 1.5.3 需要這樣做

@Configuration 
public class ValidationMessageConfig { 

    @Bean 
    public LocalValidatorFactoryBean mvcValidator(MessageSource messageSource) { 

     LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean(); 
     factory.setValidationMessageSource(messageSource); 

     return factory; 
    } 
} 

,然後它會工作。

隨着1.5.2版本和以前你可以擴展WebMVcConfigurerAdapter

@Configuration 
public class ProfileMvcConfig extends WebMvcConfigurerAdapter { 

    private MessageSource messageSource; 

    @Autowired 
    public ProfileMvcConfig(MessageSource messageSource) { 

     this.messageSource = messageSource; 
    } 

    /** 
    * This method is overridden due to use the {@link MessageSource message source} in bean validation. 
    * 
    * @return A Validator using the {@link MessageSource message source} in bean validation. 
    */ 
    @Override 
    public Validator getValidator() { 

     LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean(); 
     factory.setValidationMessageSource(messageSource); 

     return factory; 
    } 
} 

也看到了documentation