org.hibernate.validator.constraints 不选择重新加载的消息
org.hibernate.validator.constraints not picking reloaded messages
我正在尝试将 Spring 的 ReloadableResourceBundleMessageSource 用于 LocalValidatorFactoryBean,这样当我更新错误消息时它应该反映出来而无需重新启动服务器。我正在使用 Spring 4.1.4,hibernate-validator 4.3.2.Final。
以下是代码详情 -
context.xml -
<mvc:annotation-driven validator="validator" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:../conf/fileapplication</value> <!-- Messages here will override the below properties file-->
<value>/WEB-INF/application</value>
</list>
</property>
<property name="cacheSeconds" value="10"></property> <!-- Will check for refresh every 10 seconds -->
</bean>
<bean name="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource">
<ref bean="messageSource"/>
</property>
</bean>
型号-
import org.hibernate.validator.constraints.NotBlank;
public class InputForm {
@NotBlank ( message = "{required.string.blank}")
String requiredString;
控制器-
@RequestMapping(value = "/check/string", method = RequestMethod.POST)
public String checkString(
@ModelAttribute("formModel") @Valid InputForm inputForm ,
BindingResult result, Model model, HttpServletResponse response,
HttpServletRequest request) {
if (result.hasErrors()) {
model.addAttribute("formModel", inputForm);
return "userInput";
}
// Do some backend validation with String
result.reject("string.not.valid",
"String is Invalid");
model.addAttribute("formModel", inputForm);
return "userInput";
}
application.properties(在 /WEB_INF/ 文件夹中)
required.string.blank=Please enter the required string.
string.not.valid=Please enter a valid string.
文件application.properties(在/conf/文件夹中。将覆盖上面的文件)
required.string.blank=You did not enter the required string. #Does not reflect when I change here
string.not.valid=You did not enter a valid string. #Reflects when I change here
现在我面临的问题是,当我在文件 application.properties 中更新 "string.not.valid" 时,它会在运行时反映出来,我会看到更新后的消息。但是当我在文件 application.properties 中更新 "required.string.blank" 时,它不会在运行时反映出来。
请注意,覆盖部分在应用程序启动时对两条消息都工作正常。但是 "reloading" 部分不适用于 "required.string.blank".
这是我根据研究得出的结论 - 我们需要创建自己的 MessageInterpolator 并将其作为依赖项添加到验证器而不是消息源。因为当我们添加一个 messageSource 作为依赖项时,它默认被验证器缓存,任何消息重新加载 spring 都不会在验证器缓存的 messageSource 实例中生效。
详情如下:
在 context.xml 中,添加自定义 MessageInterpolator 作为对 LocalValidatorFactoryBean 的依赖而不是 messageSource:
<mvc:annotation-driven validator="validator" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:../conf/fileapplication</value> <!-- Messages here will override the below properties file-->
<value>/WEB-INF/application</value>
</list>
</property>
<property name="cacheSeconds" value="10"></property> <!-- Will check for refresh every 10 seconds -->
</bean>
<bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="messageInterpolator">
<ref bean="messageInterpolator"/>
</property>
</bean>
<bean name="messageInterpolator"
class="com.my.org.support.MyCustomResourceBundleMessageInterpolator">
<constructor-arg ref="messageSource" />
</bean>
通过扩展 Hibernate 的 org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.
创建自定义 MessageInterpolator
public class MyCustomResourceBundleMessageInterpolator extends
ResourceBundleMessageInterpolator {
public MyCustomResourceBundleMessageInterpolator(MessageSource messageSource)
{
// Passing false for the second argument
// in the super() constructor avoids the messages being cached.
super(new MessageSourceResourceBundleLocator(messageSource), false);
}
}
模型、控制器和属性文件可以与问题中的相同。
我正在尝试将 Spring 的 ReloadableResourceBundleMessageSource 用于 LocalValidatorFactoryBean,这样当我更新错误消息时它应该反映出来而无需重新启动服务器。我正在使用 Spring 4.1.4,hibernate-validator 4.3.2.Final。 以下是代码详情 -
context.xml -
<mvc:annotation-driven validator="validator" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:../conf/fileapplication</value> <!-- Messages here will override the below properties file-->
<value>/WEB-INF/application</value>
</list>
</property>
<property name="cacheSeconds" value="10"></property> <!-- Will check for refresh every 10 seconds -->
</bean>
<bean name="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource">
<ref bean="messageSource"/>
</property>
</bean>
型号-
import org.hibernate.validator.constraints.NotBlank;
public class InputForm {
@NotBlank ( message = "{required.string.blank}")
String requiredString;
控制器-
@RequestMapping(value = "/check/string", method = RequestMethod.POST)
public String checkString(
@ModelAttribute("formModel") @Valid InputForm inputForm ,
BindingResult result, Model model, HttpServletResponse response,
HttpServletRequest request) {
if (result.hasErrors()) {
model.addAttribute("formModel", inputForm);
return "userInput";
}
// Do some backend validation with String
result.reject("string.not.valid",
"String is Invalid");
model.addAttribute("formModel", inputForm);
return "userInput";
}
application.properties(在 /WEB_INF/ 文件夹中)
required.string.blank=Please enter the required string.
string.not.valid=Please enter a valid string.
文件application.properties(在/conf/文件夹中。将覆盖上面的文件)
required.string.blank=You did not enter the required string. #Does not reflect when I change here
string.not.valid=You did not enter a valid string. #Reflects when I change here
现在我面临的问题是,当我在文件 application.properties 中更新 "string.not.valid" 时,它会在运行时反映出来,我会看到更新后的消息。但是当我在文件 application.properties 中更新 "required.string.blank" 时,它不会在运行时反映出来。 请注意,覆盖部分在应用程序启动时对两条消息都工作正常。但是 "reloading" 部分不适用于 "required.string.blank".
这是我根据研究得出的结论 - 我们需要创建自己的 MessageInterpolator 并将其作为依赖项添加到验证器而不是消息源。因为当我们添加一个 messageSource 作为依赖项时,它默认被验证器缓存,任何消息重新加载 spring 都不会在验证器缓存的 messageSource 实例中生效。
详情如下:
在 context.xml 中,添加自定义 MessageInterpolator 作为对 LocalValidatorFactoryBean 的依赖而不是 messageSource:
<mvc:annotation-driven validator="validator" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:../conf/fileapplication</value> <!-- Messages here will override the below properties file-->
<value>/WEB-INF/application</value>
</list>
</property>
<property name="cacheSeconds" value="10"></property> <!-- Will check for refresh every 10 seconds -->
</bean>
<bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="messageInterpolator">
<ref bean="messageInterpolator"/>
</property>
</bean>
<bean name="messageInterpolator"
class="com.my.org.support.MyCustomResourceBundleMessageInterpolator">
<constructor-arg ref="messageSource" />
</bean>
通过扩展 Hibernate 的 org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.
创建自定义 MessageInterpolatorpublic class MyCustomResourceBundleMessageInterpolator extends
ResourceBundleMessageInterpolator {
public MyCustomResourceBundleMessageInterpolator(MessageSource messageSource)
{
// Passing false for the second argument
// in the super() constructor avoids the messages being cached.
super(new MessageSourceResourceBundleLocator(messageSource), false);
}
}
模型、控制器和属性文件可以与问题中的相同。