在企业开发应用中,我们经常会出现提供给APP,OP端的接口需要做国际化配置,一些参数校验的错误提示,以及业务处理过程中的自定义错误提示都需要进行国际化处理,由于自定义的响应码提示内容是动态,导致不能直接在配置文件中写死,以下是我自己的处理方法,如果大佬有更好的方法,可以让我公司卷以下
1.创建i18n的配置文件
在IDE项目中的resources目录下创建一个i18n的文件加,右键i18n选择Resource Bundle
在改文件下创建message.properties,message_en_US.properties,message_zn_CN.properties文件
定义一个常量类ContentConstant
private static final String VALID_TITLE_MESSAGE="valid.title";
需要参数校验的vo类中加入
@NotBlank(message = ContentConstant.VALID_TITLE_MESSAGE) private String title;
在message.properties中加入
valid.title=
在message_en_US.properties中加入
valid.title=Title cannot be empty
在message_zh_CN.properties中加入(Unicode编码)
valid.title=\u6807\u9898\u4e0d\u80fd\u4e3a\u7a7a
2.新建i18n的配置文件
@Configuration
public class I18nConfig {
@Bean
@Primary
public ResourceBundleMessageSource resourceBundleMessageSource() {
ResourceBundleMessageSource bundleMessageSource = new ResourceBundleMessageSource();
bundleMessageSource.setDefaultEncoding("UTF-8");
bundleMessageSource.setBasenames("i18n/message");
bundleMessageSource.setCacheMillis(10);
return bundleMessageSource;
}
/**
* 根据键名获取国际化描述信息
*
* @param propertyKey
* @return
*/
public String getLocaleMessage(String propertyKey) {
Locale locale = getLocale();
return resourceBundleMessageSource().getMessage(propertyKey, null, locale);
}
public Locale getLocale() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest httpServletRequest = servletRequestAttributes.getRequest();
//这里可以替换为自己前端通过头信息传递过来的区分语言的字段
String locale = httpServletRequest.getHeader(ContentConstant.HEAD_OP_LANGUAGE);
if (StringUtils.isBlank(locale)) {
return Locale.CHINA;
}
switch (locale.toLowerCase()) {
case "zh_cn":
case "zh-hans":
case "zh-CN":
case "zh-rcn":
case "zh":
return Locale.CHINA;
default:
return Locale.US;
}
}
3.新建一个处理全局异常的处理器
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@Autowired
private MessageSource messageSource;
@ExceptionHandler(value = Exception.class)
public BaseRestResponse<Void> exceptionHandler(Exception e) {
e.printStackTrace();
return new BaseRestResponse<Void>(XcallResponseStatus.SYS_EXCEPTION.getStatusCode(),
StringUtils.isBlank(e.getLocalizedMessage()) ? XcallResponseStatus.SYS_EXCEPTION.getStatusMessage() : e.getLocalizedMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public BaseRestResponse<Void> methodHandler(HttpServletRequest request, MethodArgumentNotValidException ex) {
FieldError fieldError = ex.getBindingResult().getFieldError();
// 校验注解名称
String code = fieldError.getCode();
// 校验字段名称
String field = fieldError.getField();
// 检验失败默认消息
String defaultMessage = fieldError.getDefaultMessage();
List<Object> args = Arrays.stream(Optional.ofNullable(fieldError.getArguments()).orElse(new Object[]{}))
.filter(argument -> !(argument instanceof DefaultMessageSourceResolvable))
.map(Object::toString)
.collect(Collectors.toList());
args.add(0, field);
// 默认根据注解名称取,如果没有则取默认消息
String errorMsg = getMessage(code, args.toArray(), LocaleContextHolder.getLocale(), StringUtils.EMPTY);
if (StringUtils.isBlank(errorMsg)) {
errorMsg = getMessage(defaultMessage, args.toArray(), LocaleContextHolder.getLocale(), StringUtils.EMPTY);
}
return ResponseUtils.responseError(XcallResponseStatus.SYS_EXCEPTION.getStatusCode(), StringUtils.isBlank(errorMsg) ? defaultMessage : errorMsg);
}
public String getMessage(String code, Object[] args, Locale locale, String defaultValue) {
return messageSource.getMessage(code, args, defaultValue, locale);
}
后面就是通过postman请求接口,在头信息中加入自己的定义的区分语言字段,如Accepet-Language:en_US,zh_CN