Using SpringBoot’s MessageSource.getMessage for Easy i18n Localization
SpringBoot supports internationalization out of the box; by creating a messages.properties file under resources, configuring the basename in application.yml, and using a MessageUtils wrapper that retrieves MessageSource via SpringUtils, developers can fetch localized messages with a single method call.
SpringBoot provides built‑in internationalization support, requiring only the creation of a resource file whose name starts with messages. For example, under resources/i18n/message.properties you can define key‑value pairs such as:
not.null=* 必须填写
user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效After adding the file, configure its location in application.yml:
spring:
messages:
basename: i18n/messagesNext, create a utility class MessageUtils that delegates to Spring's MessageSource:
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import com.common.utils.spring.SpringUtils;
public class MessageUtils {
/**
* Retrieve a localized message by key and optional arguments.
*/
public static String message(String code, Object... args) {
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}Because MessageUtils is not managed by Spring, it obtains the MessageSource bean via SpringUtils.getBean. The SpringUtils component implements BeanFactoryPostProcessor to store a static reference to the bean factory and offers static helper methods:
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
@Component
public final class SpringUtils implements BeanFactoryPostProcessor {
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T) beanFactory.getBean(name);
}
public static <T> T getBean(Class<T> clz) throws BeansException {
return (T) beanFactory.getBean(clz);
}
public static boolean containsBean(String name) {
return beanFactory.containsBean(name);
}
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return beanFactory.isSingleton(name);
}
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getType(name);
}
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getAliases(name);
}
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker) {
return (T) AopContext.currentProxy();
}
}With the utility in place, fetching a localized message is straightforward:
String message = MessageUtils.message("user.jcaptcha.expire");The underlying MessageSource interface (simplified) looks like:
package org.springframework.context;
import java.util.Locale;
import org.springframework.lang.Nullable;
public interface MessageSource {
@Nullable
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}The locale is obtained via LocaleContextHolder.getLocale(), ensuring the message matches the current request’s language setting. This approach centralizes message retrieval, avoids scattering hard‑coded strings, and makes it easy to modify translations by editing the properties file.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
The Dominant Programmer
Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
