国际化设计

1.书写多语言的properties文件

validation.properties

# 用户名称不能为空
userAddDto.userName.notNull=用户名称不能为空
  • 1.
  • 2.

validation_en.properties

# 用户名称不能为空
userAddDto.userName.notNull=userName cannot be empty
  • 1.
  • 2.

validation_ja.properties

# 用户名称不能为空
userAddDto.userName.notNull=ユーザー名を空白にすることはできません
  • 1.
  • 2.
结构如下

java参数解析_请求参数

2.书写配置文件

在 application.yml文件中加入配置

spring:
    # i18 message 配置,对应 MessageSourceProperties 配置类
  messages:
    basename: i18n/validation
    encoding: UTF-8 # 使用 UTF-8 编码
    #配置中文编码乱码问题
  http:
    encoding:
      charset: UTF-8
      enabled: true
      force: true
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

编写 ValidationConfiguration.java文件

@Configuration
public class ValidationConfiguration {

    /**
     * 参考 {@link ValidationAutoConfiguration#defaultValidator(ApplicationContext)} 方法,构建 Validator Bean
     *
     * @return Validator 对象
     */
    @Bean
    public Validator validator(MessageSource messageSource, ApplicationContext applicationContext) {
        // 创建 LocalValidatorFactoryBean 对象
        LocalValidatorFactoryBean validator = ValidationAutoConfiguration.defaultValidator(applicationContext);
        // 设置 messageSource 属性,实现 i18 国际化
        validator.setValidationMessageSource(messageSource);
        // 返回
        return validator;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

3.使用方式

/**
     * 用户名称
     * 注意:SpringMVC 通过 Accept-Language 请求头,实现 i18n 国际化。
     * 使用这种方式验证参数,要在请求的header中增加参数:Accept-Language=en/ja
     */
    @ApiModelProperty(value = "用户名称", required = true)
    @NotBlank(message = "{userAddDto.userName.notNull}")
    private String userName;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
注意:如果默认没有设置语言则为系统默认语言为标准

4.重启服务,测试

在header添加Accept-Language参数,测试英文。达到预想结果

java参数解析_用户名_02


测试不存在的语言


java参数解析_用户名_03

在此多语言参数验证就已实现完成,细心的网友会看见 请求参数不正确并没有随着多语言的编号而变化

设计业务提示国际化

设计业务提示多语言,可以参照上面的参数验证做出设计。但是难点在于如何让业务枚举或者异常枚举按照语言不同,选择不同的properties文件做出处理。按照这个思想,可以在枚举中定义一个code,通过这个code和前端传的语言来确定properties文件

1.编写properties文件

result_zh.properties

# 请求参数不正确
REQUEST_PARAM_ERROR=请求参数不正确:%s
  • 1.
  • 2.

result_en.properties

# 请求参数不正确
REQUEST_PARAM_ERROR=Incorrect request parameters:%s
  • 1.
  • 2.

result_ja.properties

# 请求参数不正确
REQUEST_PARAM_ERROR=要求パラメータが正しくありません:%s
  • 1.
  • 2.
结构如下

java参数解析_Source_04

2.枚举设计

//    REQUEST_PARAM_ERROR(125, "请求参数不正确")	//以前的枚举设计
REQUEST_PARAM_ERROR(125, "REQUEST_PARAM_ERROR") //现在的设计
  • 1.
  • 2.

定义一个接口,使枚举类都实现这个接口

public interface Language {

    String LangCode();

    /**
     * 获取语言提示
     * @param params 参数
     * @return 消息
     */
    String getMsg(Object... params);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

3.编写核心文件ResultResource.java

public class ResultResource {

    /**
     * 将国际化信息存放在一个map中
     */
    private static final Map<String, String> RESULT_MESSAGES = new ConcurrentHashMap<String, String>();
    /**
     * 存放Properties文件
     */
    private static final Map<String, Properties> PROPERTIES = new HashMap<>();

    /**
     * 定义默写语言数组,若不需要修改这个值即可。后期可采用配置文件或者数据库维护动态管理
     */
    private static final List<String> DEFAULT_LANG = Arrays.asList("zh","en","ja");

    /**
     * 获取国际化信息
     */
    public static String getMessage(String key, Object... params) {
        //获取语言,这个语言是从header中的Accept-Language中获取的,
        //会根据Accept-Language的值生成符合规则的locale,如zh、pt、en等
        Locale locale = LocaleContextHolder.getLocale();
        //为空,默认中文
        if (!ArrayUtil.contains(Locale.getAvailableLocales(), locale) || !DEFAULT_LANG.contains(locale.getLanguage())) {
            locale = Locale.getDefault();
        }
        Properties properties = PROPERTIES.get(locale.getLanguage());
        if (Objects.isNull(properties)) {
            properties = propertiesByLangCode(locale);
        }
        //设置一个key
        String popKey = doKey(locale.getLanguage(), key);
        String message = RESULT_MESSAGES.get(popKey);
        if (message == null) {
            //在这里读取配置信息
            message = properties.getProperty(key);
            RESULT_MESSAGES.put(popKey, message);
        }
        //此处获取并返回message
        if (params != null) {
            return String.format(message, params);
        }
        return message;
    }

    /**
     * 清除国际化信息
     */
    public static void flushMessage() {
        RESULT_MESSAGES.clear();
    }

    private static String doKey(String langCode, String key) {
        return langCode + StringConstant.LINE + key;
    }

    private static Properties propertiesByLangCode(Locale locale) {
        String langCode = locale.getLanguage();
        Properties properties = null;
        try {
            String resourceUrl = I18nConstant.RESULT_BASE_NAME + StringConstant.LINE + langCode + ".properties";
            EncodedResource encodedResource = new EncodedResource(new ClassPathResource(resourceUrl), "UTF-8");
            properties = PropertiesLoaderUtils.loadProperties(encodedResource);
            PROPERTIES.put(langCode, properties);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.

枚举类做出以下调整

@Getter
public enum ResultEnum implements Language {
    /**
     * 请求参数不正确
     */
    REQUEST_PARAM_ERROR(125, "REQUEST_PARAM_ERROR")
//    REQUEST_PARAM_ERROR(125, "请求参数不正确")

 private Integer code;

    private String langCode;

    ResultEnum(int code, String langCode) {

        this.code = code;
        this.langCode = langCode;
    }
    @Override
    public String LangCode() {
        return langCode;
    }

    @Override
    public String getMsg(Object... params) {
        return ResultResource.getMessage(langCode, params);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

4.修改全局异常类

java参数解析_Source_05

5.项目重启,测试允许

java参数解析_Source_06


java参数解析_请求参数_07