如何在 Spring 中使用从属性文件获取的错误消息的注释验证?

Posted

技术标签:

【中文标题】如何在 Spring 中使用从属性文件获取的错误消息的注释验证?【英文标题】:How to use annotation validation in Spring with error message gotten from properties file? 【发布时间】:2011-08-12 19:06:16 【问题描述】:

我是春季新手。

我在我的域类中设置了这样的验证:

public class Worker 

    @NotNull(message="Name must be input")
    @Size(min=1,max=50, message="Name must not exceed 50 characters")
    private String name;
...


这是jsp文件:

<form:input path="code" readonly="false" />
<font color="red"><form:errors path="code" />

以及控制器代码:

@RequestMapping(value="/test",method=RequestMethod.POST)
    public void form(@Valid Worker worker, BindingResult result) 

        if (result.hasErrors()) 
            return;
        
...

它有效,但是如何在我的消息源中用一些文本(如 worker.name.overflow)替换“名称不得超过 50 个字符”?是否需要在 BindingResult 中添加 messageResolver?

所有搜索结果似乎都在说要编写自定义验证器类,但我现在想使用注释。我很确定有办法,因为在this question 有人已经做到了。

【问题讨论】:

【参考方案1】:

要告诉 Hibernate 验证器对代码进行查找,请将 message 的值放在大括号中,例如 @NotNull(message="worker.name.NotNull",然后将翻译放在类路径根目录下的 ValidationMessages.properties (/WEB-INF/classes , Maven 中的资源文件夹等)。

验证器实现独立地查找它们,然后它们继续 BindingResult 已经被翻译为默认消息。发生在 Spring 消息源之外。理论上,您可以覆盖 LocalValidatorFactory bean,将验证器的消息输出作为代码放到 Errors 对象上,然后在注释中去掉大括号,以便 Hibernate Validator 将其传递。将 JSR-303 ConstraintViolations 转换为 Spring Errors 的源代码非常简单,易于阅读和扩展。它只是将注解的名称作为代码,将注解属性作为 args,然后将验证器的翻译作为默认消息。你可以阅读实现here。

您可以将javax.validation.MessageInterpolator 添加到您的javax.validation.Configuration 以告诉它在其他属性文件中查找消息。如果您使用的是 Spring LocalValidatorFactory bean,它上面有一个 setMessageInterpolator(),您可以使用它来注入一个。检查 this 源以获取 Hiberate 提供程序实现。

【讨论】:

我已经像你的第一段那样做了:在WEB-INF中放一个文件名ValidationMessages.properties,并为消息添加大括号,但它没有改变。似乎找不到 ValidationMessages.properties。 抱歉我的错误,我错过了将 ValidationMessages.properties 放在类路径中的部分。如果您能告诉我如何修改此默认位置,我将不胜感激? 您可以更具体地更改属性文件位置吗?我正在使用弹簧,但你的解释对我来说听起来像是希腊语! localValidatorFactoryBean.setMessageInterpolator(new ResourceBundleMessageInterpolator(new AggregateResourceBundleLocator(Arrays.asList("my.package.MyFileName", "my.other.package.AnotherFileName")))); LocalValidatorFactoryBean 有一个validationMessageSource 属性,您可以在该属性上设置一个Spring MessageSource,这比设置您自己的MessageInterpolator 更容易。【参考方案2】:

这是对问题的一点解释。

@Size(min = 1, max = 50, message = "Email size should be between 1 and 50")

现在从验证标签中删除 message = "Email size should be between 1 and 50" 。

这样做之后,您的注释将是这样的。

@Size(min = 1, max = 50)

现在在控制器端调试提交表单时调用的方法。以下是我在用户点击提交时接收请求的方法。

public static ModelAndView processCustomerLoginRequest(IUserService userService, LoginForm loginForm, 
    HttpServletRequest request, HttpSession session, BindingResult result, String viewType, Map<String, LoginForm> model)

现在在方法的第一行放置一个调试点并调试参数“result”。

BindingResult result

调试时你会在codes数组中找到这样的字符串。

Size.loginForm.loginId

现在在您的属性文件中定义此字符串并针对该字符串定义一条消息。编译并执行。只要没有验证该注释,就会显示该消息。

Size.loginForm.loginId=email shouldn't be empty.

基本上,spring 将自己的字符串作为其属性文件消息的键。在上面的键

Size(@Size) = validation annotation name
loginForm = My Class Name
loginId = Property name in LoginForm class.

【讨论】:

以上是关于如何在 Spring 中使用从属性文件获取的错误消息的注释验证?的主要内容,如果未能解决你的问题,请参考以下文章

如何在spring项目中读取属性文件?

SpringMVC利用Spring自带验证框架验证获取错误信息出现乱码问题

[坑]Spring利用注解@Value获取properties属性为null

如何在 Spring @Value 注解中正确指定默认值?

如何从 Spring Boot Config Server 提供的其他属性文件中的 application.properties 获取密钥?

spring-boot 单元测试获取应用程序属性