栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java > SpringBoot

Spring Boot国际化

SpringBoot 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot国际化

spring-boot-starter-web里面有国际化需要的API,因此我们不需要引入其他的API了。

1.定义国际化的配置文件
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;

import java.util.Locale;


@Configuration
public class I18nConfiguration {

    
    @Bean
    public LocaleResolver localeResolver() {
 AcceptHeaderLocaleResolver acceptHeaderLocaleResolver = new AcceptHeaderLocaleResolver();
 acceptHeaderLocaleResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
 return acceptHeaderLocaleResolver;
    }

    
    @Bean
    public ReloadableResourceBundleMessageSource messageSource() {
 ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
 //设置国际化配置文件存放目录
 messageSource.setbasename("classpath:i18n/messages");
 //设置加载资源的缓存失效时间,-1表示永久有效,默认为-1
 messageSource.setCacheSeconds(-1);
 //设定 Resource Bundle 编码方式,默认为UTF-8
 messageSource.setDefaultEncoding("UTF-8");
 return messageSource;
    }
}

AcceptHeaderLocaleResolver:Spring内置的国际化处理,获取Http请求头中的Accept-Language属性,判断当前环境是哪种语言。

2.在resources目录下,创建i18n目录和两个国际化的文件,要以message开头

messages_en_US.properties,英文提示

delete.success=delete success.
save.success=Save Success.
update.success=Update Success.

messages_zh_CN.properties,中文提示

delete.success=删除成功
save.success=保存成功
update.success=更新成功
3.定义一个工具类,根据当前语言环境和国际化提示中的key获取对应的提示
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Component;

import java.util.Locale;


@Component
public class I18nUtils {

    private static ReloadableResourceBundleMessageSource messageSource;

    @Autowired
    I18nUtils(ReloadableResourceBundleMessageSource messageSource) {
 I18nUtils.messageSource = messageSource;
    }

    public static String toLocale(String message) {
 Locale locale = LocaleContextHolder.getLocale();
 return messageSource.getMessage(message, null, locale);
    }
}

4.为了统一管理key,我们用枚举保存。
import lombok.AllArgsConstructor;

import java.util.stream.Stream;


@AllArgsConstructor
public enum I18nEnum {

    SAVE_SUCCESS("save.success"),
    UPDATE_SUCCESS("update.success"),
    DELETE_SUCCESS("delete.success"),
    ;

    private final String message;

    public String message() {
 return this.message;
    }

    public static boolean exists(String s) {
 return Stream.of(I18nEnum.values())
  .map(I18nEnum::message)
  .anyMatch(s::equals);
    }

}

注:用枚举是因为我们在全局异常处理的时候,要获遍历枚举里面的常量,从而判断是否要国际化。

5.使用
@PostMapping
public ResponseEntity save(@RequestBody @Validated UserRequestVO requestVO) {
    userService.save(requestVO);
    return ResponseEntity.status(HttpStatus.CREATED)
 .body(I18nUtils.toLocale(I18nEnum.SAVE_SUCCESS.message()));
}

这样一来,会就完成了提示消息国际化功能。

上面的做法不能让入参校验进行国际化,比如@NotNull(message = "请传入xxxx")。因此,我们还需要改造,定义两组提示信息

messages_zh_CN.properties

paging.tip=请传入分页参数

messages_en_US.properties

paging.tip=Please pass in paging parameters

改造注解上的提示信息:@NotNull(message = "paging.tip")

import lombok.Data;

import javax.validation.constraints.NotNull;


@Data
public class PageRequestVO {

    @NotNull(message = "paging.tip")
    private Integer page;

    @NotNull(message = "paging.tip")
    private Integer size;

}

现在一般提交数据的方式用两种:表单提交和JSON格式

如果是表单提交,校验不通过的话,会抛出BindException。JSON格式的提交,校验不通过则会抛出MethodArgumentNotValidException。所以,我们要拦截这两种异常处理

import com.isecstar.print.common.enums.I18nEnum;
import com.isecstar.print.common.utils.I18nUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException methodArgumentNotValidException, HttpServletRequest request) {
 return getError(methodArgumentNotValidException, request);
    }

    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map bindException(BindException bindException, HttpServletRequest request) {
 return getError(bindException, request);
    }

    private Map getError(Exception e, HttpServletRequest request) {
 log.error("", e);
 Map error = new HashMap<>(5);
 String message = e.getMessage();
 error.put("message", I18nEnum.exists(message) ? I18nUtils.toLocale(message) : message);
 error.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
 if (e instanceof MethodArgumentNotValidException) {
     MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) e;
     BindingResult bindingResult = methodArgumentNotValidException.getBindingResult();
     // messageList就是写在@NotNull(message = "")message的信息, 这里获取到的是 paging.tip
     Set messageList = bindingResult.getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.toSet());
     List globalizationMessage = messageList.stream().map(I18nUtils::toLocale).collect(Collectors.toList());
     error.put("message", globalizationMessage);
     error.put("httpStatus", HttpStatus.BAD_REQUEST);
     error.put("code", HttpStatus.BAD_REQUEST.value());
 } else if (e instanceof BindException) {
     BindException bindException = (BindException) e;
     // messageList就是写在@NotNull(message = "")message的信息, 这里获取到的是 paging.tip
     Set messageList = bindException.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.toSet());
     List globalizationMessage = messageList.stream().map(I18nUtils::toLocale).collect(Collectors.toList());
     error.put("message", globalizationMessage);
     error.put("httpStatus", HttpStatus.BAD_REQUEST);
     error.put("code", HttpStatus.BAD_REQUEST.value());
 }
 error.put("path", request.getRequestURI());
 error.put("timestamp", LocalDateTime.now());
 return error;
    }
}

这样一来,我们就可以在校验中,对外国际化之后的异常信息。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号