国际化资源加载
尝试使用application配置
在尝试使用application配置加载文案资源时,会抛出“NoSuchMessageException: No message found under code XXX”的异常,打断点发现自动注入的MessageSource是DelegatingMessageSource,而且没有对资源文件做任何加载,
细节原因参考:https://segmentfault.com/a/1190000010757338
bean配置
放弃application配置后,我想主动对MessageSource进行注入,使用ReloadableResourceBundleMessageSource。
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages/messages");
messageSource.setCacheSeconds(messagesCache);
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
basename是文案资源的路径,第一个messages是目录,第二个messages是默认文案和其他语言文案的前缀。
在返回结果加入文案
@ControllerAdvice
public class I18nResponseBodyAdvice implements ResponseBodyAdvice<ResultCollect> {
@Autowired
private MessageSource messageSource;
@Autowired
private AccountService accountService;
// supports方法判断该返回结果是否要被拦截,如果返回true,则执行beforeBodyWrite方法。
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return ResultCollect.class.isAssignableFrom(methodParameter.getParameterType());
}
@Override
public ResultCollect beforeBodyWrite(ResultCollect resultCollect, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
HttpServletRequest request = ((ServletServerHttpRequest) serverHttpRequest).getServletRequest();
String local = accountService.getCookie(request, "user-locale");
Locale locale;
if (StringUtils.isNotBlank(local)) {
// locale: zh-CN or en-US
String[] arr = local.split("-");
locale = new Locale(arr[0], arr.length > 1 ? arr[1] : "");
} else {
locale = Locale.US;
}
if (resultCollect != null) {
resultCollect.setMsg(messageSource.getMessage(resultCollect.getKey(), null, locale));
}
return resultCollect;
}
}
supports方法判断该返回结果是否要被拦截,如果返回true,则执行beforeBodyWrite方法。
beforeBodyWrite方法的参数ServerHttpRequest、ServerHttpResponse,分别传递的是ServletServerHttpRequest、ServletServerHttpResponse,均属于org.springframework.http包下的类型;而在拦截器中常用的HttpServletRequest、HttpServletResponse属于javax.servlet包下的类型。
以zh-CN为例,messageSource.getMessage查找的资源文件顺序为:
- messages_zh_CN.properties
- messages.properties
- messages_zh.properties