不使用属性文件与资源束配置Spring Validator及JSP错误消息
Great question! The org.springframework.context.NoSuchMessageException you're hitting is because Spring's default validation system expects to resolve error message codes from resource bundles (like messages.properties) by default. If you want to skip property files entirely, here are some solid, localized alternatives:
1. Use Spring's StaticMessageSource (Simple Hardcoded Localized Messages)
Spring provides a built-in StaticMessageSource that lets you register localized messages directly in code—no property files required. It's perfect if your error messages are static and don't need frequent updates.
Example Configuration (Java Config):
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.StaticMessageSource; import java.util.Locale; @Configuration public class ValidationConfig { @Bean public StaticMessageSource messageSource() { StaticMessageSource messageSource = new StaticMessageSource(); // Register English (en_IN) message messageSource.addMessage( "please enter user firstname.keyUserRegistration.firstName", new Locale("en", "IN"), "Please enter your first name" ); // Add other locales as needed (e.g., Hindi) messageSource.addMessage( "please enter user firstname.keyUserRegistration.firstName", new Locale("hi", "IN"), "कृपया अपना पहला नाम दर्ज करें" ); return messageSource; } }
This replaces Spring's default message source, so when your validator uses rejectValue with the message code, it will pull the localized message directly from this in-memory source instead of looking for property files.
2. Build a Custom MessageSource for Dynamic Localized Messages
If you need to pull localized messages from a database, CMS, or another dynamic source, create a custom implementation of MessageSource by extending AbstractMessageSource. This gives you full control over where messages are stored and retrieved.
Example Custom Message Source:
import org.springframework.context.support.AbstractMessageSource; import java.text.MessageFormat; import java.util.HashMap; import java.util.Locale; import java.util.Map; public class DatabaseBackedMessageSource extends AbstractMessageSource { // Simulate a database lookup - replace with actual DB calls in production private final Map<Locale, Map<String, String>> localizedMessages = new HashMap<>(); public DatabaseBackedMessageSource() { // Initialize English messages Map<String, String> enInMessages = new HashMap<>(); enInMessages.put("please enter user firstname.keyUserRegistration.firstName", "Please enter your first name"); localizedMessages.put(new Locale("en", "IN"), enInMessages); // Initialize Hindi messages Map<String, String> hiInMessages = new HashMap<>(); hiInMessages.put("please enter user firstname.keyUserRegistration.firstName", "कृपया अपना पहला नाम दर्ज करें"); localizedMessages.put(new Locale("hi", "IN"), hiInMessages); } @Override protected MessageFormat resolveCodeInternal(String code, Locale locale) { // Fallback to en_IN if the requested locale isn't available Map<String, String> messages = localizedMessages.getOrDefault(locale, localizedMessages.get(new Locale("en", "IN"))); String message = messages.get(code); return message != null ? new MessageFormat(message, locale) : null; } }
Register It in Spring:
@Bean public MessageSource messageSource() { return new DatabaseBackedMessageSource(); }
This approach is ideal if you need to update messages without redeploying your app, or if you already have localized content stored in a database.
3. Directly Inject Localized Messages in Your Validator
If you want to skip the message source entirely, you can handle localization directly in your validator by fetching the current request's locale and returning the appropriate message. This avoids any message code resolution altogether.
Example Validator:
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.validation.Errors; import org.springframework.validation.Validator; import org.springframework.util.StringUtils; import java.util.Locale; public class UserRegistrationValidator implements Validator { @Override public boolean supports(Class<?> clazz) { return UserRegistration.class.equals(clazz); } @Override public void validate(Object target, Errors errors) { UserRegistration user = (UserRegistration) target; Locale currentLocale = LocaleContextHolder.getLocale(); if (StringUtils.isEmpty(user.getFirstName())) { String errorMessage; // Determine message based on current locale if (new Locale("hi", "IN").equals(currentLocale)) { errorMessage = "कृपया अपना पहला नाम दर्ज करें"; } else { errorMessage = "Please enter your first name"; } // Pass null as the message code to skip resource bundle lookup errors.rejectValue("firstName", null, errorMessage); } } }
Note the null in rejectValue—this tells Spring not to try resolving a message code, and to use the provided message directly.
Which Option is Best?
- Use
StaticMessageSourcefor simple, static localized messages (low overhead, easy to set up). - Use a custom
MessageSourceif you need dynamic, updatable messages (database/CMS integration). - Use direct validator messages only if you have a small number of validation rules and don't want to maintain a message source (though this couples localization logic to your validator, which isn't ideal for large apps).
All of these approaches will eliminate the NoSuchMessageException since they bypass Spring's default resource bundle lookup.
内容的提问来源于stack exchange,提问作者vikas patidar

