Spring中实现自定义异常国际化需三步:定义携带错误码的异常类、配置支持多语言的MessageSource、在@ControllerAdvice中用MessageSource按Locale翻译错误码并封装响应。

在 Spring 框架中实现自定义异常的国际化消息提示,核心在于将异常与国际化的资源绑定,让同一异常在不同语言环境下返回对应的语言文案。关键不是只抛异常,而是让异常携带可解析的错误码,并通过 MessageSource 动态翻译。
定义可携带错误码的自定义异常
自定义异常应继承 RuntimeException(或 Exception),并持有唯一、语义清晰的错误码(如 "user.not.found"),不直接存具体消息文本。
- 错误码命名建议采用小写+点分隔风格,便于后续映射到 properties 文件中的 key
- 可添加一个可选的参数数组(
Object... args),用于动态填充占位符(如{0},{1}) - 不重写
getMessage()直接返回硬编码字符串,而是留空或返回错误码,交由统一处理层翻译
示例:
public class BusinessException extends RuntimeException {
private final String code;
private final Object[] args;
public BusinessException(String code, Object... args) {
super(code); // 仅作标识,不用于展示
this.code = code;
this.args = args;
}
public String getCode() { return code; }
public Object[] getArgs() { return args; }
}
配置 MessageSource 支持多语言资源
Spring 默认使用 ResourceBundleMessageSource 加载 .properties 文件,需在配置类或 application.yml 中声明 bean 并指定基础名称和编码。
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 资源文件按约定命名:如
messages.properties(默认)、messages_zh_CN.properties、messages_en_US.properties - 确保文件保存为 UTF-8 编码,中文内容用 Unicode 转义(或启用
setUseCodeAsDefaultMessage(true)避免乱码) - 推荐设置
setCacheSeconds(3600)提升性能,避免频繁读取文件
Java 配置示例:
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename("messages");
source.setDefaultEncoding("UTF-8");
source.setUseCodeAsDefaultMessage(true);
source.setCacheSeconds(3600);
return source;
}
统一异常处理器中完成翻译与响应封装
使用 @ControllerAdvice + @ExceptionHandler 捕获自定义异常,在处理器内调用 MessageSource.getMessage() 获取本地化消息。
- 传入错误码、参数数组、当前请求的
Locale(可通过RequestContextHolder或方法参数获取) - 建议封装统一响应结构(如
Result<T>),包含 code、message、data 字段,前端只认这个格式 - 若未找到对应 key,默认返回错误码本身,避免空消息
示例处理器片段:
@ExceptionHandler(BusinessException.class)
@ResponseBody
public Result<?> handleBusinessException(BusinessException e, HttpServletRequest request) {
Locale locale = RequestContextUtils.getLocale(request);
String message = messageSource.getMessage(e.getCode(), e.getArgs(), e.getCode(), locale);
return Result.fail(e.getCode(), message);
}
在 properties 文件中维护多语言文案
每个语言版本的 messages_*.properties 文件只需按 key-value 形式填写,key 即异常中的错误码,value 是对应语言的提示文本,支持 {0} 占位符。
-
messages_zh_CN.properties:user.not.found=用户【{0}】不存在 -
messages_en_US.properties:user.not.found=User [{0}] not found - 占位符顺序与
new BusinessException("user.not.found", "zhangsan")中参数顺序一致 - 避免在文案中写死业务 ID 或敏感信息,所有动态内容都走占位符
不复杂但容易忽略:确保 Controller 层抛出的是你定义的异常类型,且不要在 service 里提前调用 getMessage() —— 翻译必须发生在请求上下文中,才能拿到正确的 Locale。

















