Java Web国际化及乱码解决方案

一、背景

  1. 项目过程中,难免需要提示中文或者英文提示信息,有了国际化,方便切换;
  2. 实际项目中,一般都不允许直接把中文提示信息写在代码中,避免其他国家程序猿看不懂(国际化公司和开源项目涉及),也容易招来其他国家的恶意攻击。比如菊花公司把中文写在代码中就算成非常严重的违规。

二、目标

  1. 在项目中引入简单易用的国际化框架,方便同事使用。

三、步骤

  1. Java SDK自带国际化API:java.util.ResourceBundle,使用也特别简单,目前就选定使用它;
  2. 对应的国际化资源目录结构如下:
    国际化截图
    说明下:我这里是采用maven作为代码构建工具,资源默认路径是在src/main/resources,编译后对应路径为$bin/classes目录。$bin表示代码生成class的根路径。$bin在maven中实际默认为:与src同级的target目录。
  3. 了解了下ResourceBundle的用法,编写测试类:
import org.junit.Test;

import java.io.UnsupportedEncodingException;
import java.util.Locale;
import java.util.ResourceBundle;

import static org.junit.Assert.assertTrue;

public class I18nTest
{
    @Test
    public void testI18n() throws UnsupportedEncodingException
    {
        Locale locale = Locale.getDefault();
        System.out.println("current locale:" + locale.toString());
        ResourceBundle bundle = ResourceBundle.getBundle("i18n/tips", locale);
        String msg = bundle.getString("test.failed");
        System.out.println("current msg:" + msg);
        assertTrue(null != msg);
    }
}

其中ResourceBundle.getBundle的第一个参数叫baseName,就是相对于classes目录的文件路径,因为涉及国际化,所以不能带上国家(区域)后缀,也不需要带上porperties这个文件类型后缀。记住baseName是相对路径,不要在i18n/tips前面加上‘/’。
4. 国家(区域)后缀有标准的定义。也有网友总结的参照表
5. 执行上述测试代码过程中,发现输入中文时,会出现乱码。原因:IDE工具默认的字符编码不是UTF-8。建议把IDE的所有文件类型编码都设置成UTF-8,同时设置properties内容转换为ASCII码。我使用的是IDEA,设置如下:
properties编码设置
6. 设置后,会发现tips_zh_CN.properties中文展示如下:
国际化展示
7. 再次执行,乱码消失了。
8. 验证通过后,封装对应的工具类:

public final class I18nUtils
{
    /**
     * 获取国际化值
     *
     * @param key
     * @return
     */
    public static String get(String key)
    {
        String value = BUNDLE.getString(key);
        if (StringUtils.isEmpty(value))
        {
            value = StringUtils.EMPTY;
        }
        LOGGER.info("i18n:[{}]={}", key, value);
        return value;
    }

    private static final Logger LOGGER = LogManager.getLogger(I18nUtils.class);

    //国际化文件路径
    private static final String I18N_FILE = "i18n/tips";

    //国际化bundle
    private static ResourceBundle BUNDLE;

    static
    {
        BUNDLE = ResourceBundle.getBundle(I18N_FILE, Locale.getDefault());
    }

    private I18nUtils()
    {
    }
} 
  1. 在springboot框架下使用该工具类给页面返回中文结果时,发现还是存在乱码。springboot的application.properties编码配置如下:
server.tomcat.uri-encoding=UTF-8
spring.banner.charset=UTF-8
spring.messages.encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.force=true
spring.http.encoding.enabled=true

给前台返回结果的代码(过滤器)如下:

           Writer writer = response.getWriter();
           String failedMsg = I18nUtils.get(“test.failed”);
           String failedJson = JsonUtils.toJson(failedMsg);
           writer.write(failedJson);
           writer.flush();
  1. 刚开始考虑还有没有什么编码设置给遗漏了,包括是不是springboot集成的springmvc部件没有指定编码,结果发现根本不起作用。后面只能怀疑是response响应数据时,没有指定编码。
  2. 在上述代码前加上ContentType设置(“application/json;utf-8”):
            response.setContentType(ContentType.APPLICATION_JSON.toString());

问题解决。

四、总结

  1. 在这么多年的Java Web项目中,碰到了很多次乱码的问题,而且每次问题都还不一样,解决方案也不一样T_T;
  2. Java自带的国际化工具比想象的好用;
  3. 网上关于Java自带国际化的使用大多只说了部分问题和部分代码,基本上没有看到像我这样完整写出来的,希望对你有帮助;
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值