`

java国际化之(二)---springMVC

阅读更多

ResourceBundle

 

上一章java国际化之()---jdk相关api,主要对jdk中对国际化支持的API进行了讲解。在jdk国际化api中还有一个重要的类上一章没讲---ResourceBundle类,该类会在spring MVC国际化读取配置的时候用到,所以放到这次讲解。

 

现在来看下ResourceBundle类,它能轻松的选择和读取特定用户语言区域配置文件,并根据指定key查询对应的属性值。ResourceBundle是个抽象类,要想创建它的实例对象,只能通过调用其静态工厂方法getBundle方法实现。通过阅读该方法的源码可以发现,其最终会创建一个PropertyResourceBundle类的实例(PropertyResourceBundleResourceBundle的子类类),配置文件是.properties类型,并读取配置文件中的值放到HashMap中,关键源码如下:

// stream为从.properties配置文件读入的输入流
bundle = new PropertyResourceBundle(stream);
 
// PropertyResourceBundle的构造方法
public PropertyResourceBundle (InputStream stream) throws IOException {
        Properties properties = new Properties();
        properties.load(stream);
        lookup = new HashMap(properties);
    }

 

 

我们再来看getBundle方法的定义:

public static final ResourceBundle getBundle(String baseName, Locale locale)
public static final ResourceBundle getBundle(String baseName)//自动获取默认的locale

 

baseName为配置文件的 基准名,用户可以任意定义,假设这里定义为” message” locale为区域语言,比如汉语_中国,通过zh_CN表示。最终确定的配置文件即为:messages_zh_CN.properties,如果没有找到该文件,会自动寻找默认文件messages.properties,如果也没找到,抛出MissingResourceException异常。

 

看个例子,首先准备三个.properties配置文件,放到程序执行的classpath下。比如 我是在diea中执行的,可以放到编译完成的classes目录下:



 

 

messages_en.properties配置文件中的内容为:

productname.required.product.name=Please enter a name
price.negative=Invalid price

 

 

messages_zh_CN.propertiesmessages.properties配置文件中的内容相同,内容为:

productname.required.product.name=请输入商品名称
price.negative=价格不合法

 

 

再看下main方法:

public static void main(String[] args) {
        //Locale lc = Locale.CHINA; //汉语中国地区
        Locale lc = new Locale("en");//英语地区
        ResourceBundle rb = ResourceBundle.getBundle("messages",lc);
        System.out.println(rb.getString("productname.required.product.name"));
    }

 

执行mian方法,打印信息为:

Please enter a name

 

lc改为Locale.CHINA,再执行main方法,打印信息为乱码。这是由于java原生支持的是Unicode编码,这里需要把对应的中文转陈Unicode编码。转Unicode可以使用java自带的native2ascii工具,也可以写段程序来实现类似的转换,同时也可以实现反转。这里不对native2ascii工具进行讲解,感兴趣的可以百度下,我们来看下通过程序把汉字转换为Unicode编号的实现:

public static String encodeUnicode(String inStr) {
        char[] myBuffer = inStr.toCharArray();
 
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < inStr.length(); i++) {
            char ch = myBuffer[i];
            if (ch < 10) {
                sb.append("\\u000" + (int) ch);
                continue;
            }
            UnicodeBlock ub = UnicodeBlock.of(ch);
            if (ub == UnicodeBlock.BASIC_LATIN) {
                // 英文及数字等
                sb.append(myBuffer[i]);
            } else if (ub == UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
                // 全角半角字符
                int j = myBuffer[i] - 65248;
                sb.append((char) j);
            } else {
                // 汉字
                int s = myBuffer[i];
                String hexS = Integer.toHexString(Math.abs(s));
                String unicode = "\\u" + hexS;
                sb.append(unicode.toLowerCase());
            }
        }
        return sb.toString();
}
 
public static void main(String[] args) {
        System.out.println(encodeUnicode("请输入商品名称"));
        System.out.println(encodeUnicode("价格不合法"));
    }
 

 

执行mian方法,打印信息为:

\u8bf7\u8f93\u5165\u5546\u54c1\u540d\u79f0
    \u4ef7\u683c\u4e0d\u5408\u6cd5

 

将这些字符用户来替换messages_zh_CN.propertiesmessages.properties配置文件中的汉字,再次执行上一个mian方法:

public static void main(String[] args) {
        Locale lc = Locale.CHINA; //汉语中国地区
        //Locale lc = new Locale("en");//英语地区
        ResourceBundle rb = ResourceBundle.getBundle("messages",lc);
        System.out.println(rb.getString("productname.required.product.name"));
}

 

打印信息为:

请输入商品名称

关于ResourceBundle类的用法讲解,到处结束。至此我们已经讲解jdk中对国际化支持的相关api,通过这些api我们已经可以实现国际化程序的开发。但我们不用这么麻烦的自己去编码实现国际化,现在主流的mvc框架都提供国际化支持,底层其实就是基于上述讲解的jdk国际化api实现的。了解了java国际化实现原理后,我们接下来看看Spring MVC对国际化的支持。

 

Spring MVC 国际化配置

 

Spring MVC的国际化配置主要包含两部分:选择和读取正确的属性配置文件;告诉Spring MVC使用哪种语言区域。

 

1、选择和读取正确的属性配置文件,是通过ReloadableResourceBundleMessageSource配置,其底层实际上是调用ResourceBundle实现的。配置方式如下:

<!-- 资源文件 -->
    <bean id="messageSource"
          class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames" >
            <list>
                <value>classpath:/resource/messages</value>
                <value>classpath:/resource/labels</value>
            </list>
        </property>
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>

 

其中messageslabels为国际化配置文件的基准名,根据业务的需要可以配置多个。对应的配置文件列表为:



 

注意:所有配置文件在程序启动时,读入到内存。如果配置文件修改后,需要重新启动程序。

多版本的配置文件准备好后,就要告诉Spring MVC使用哪个国家的配置。

 

2、告诉Spring MVC使用哪种语言区域:Spring MVC支持4种方式的配置,告诉Spring MVC使用哪种语言区域,根据具体业务场景使用,4种方式分别讲解如下。

ACookieLocaleResolver:通过cookie方法,该方式会在用户的浏览器cookie中记住用户的区域语言,并在程序运行过程中,获取指定区域语言的属性配置文件里的消息。配置方式如下:

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
         <property name="cookieName" value="clientlanguage"/>
         <property name="cookieMaxAge" value="94608000"/>
         <property name="defaultLocale" value="en" />
</bean>

 

cookieName cookie名称;cookieMaxAgecookie的过期时间;defaultLocale,默认的区域语言,该方式可以通过构造请求改变cookie中的值,以实现改变区域语言。

 

BAcceptHeaderLocaleResolver:通过读取请求头中的accept-language中的区域语言,并在程序运行过程中,获取指定区域语言的属性配置文件里的消息。配置方式如下:

<bean id="localeResolver"
          class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver">
</bean>

 

该方式,可以在浏览器中修改语言选项完成区域语言的修改。修改方式,以chrome为例:设置—>高级设置à语言和输入设置à添加



 

然后把需要指定的语言拖动到顶部 保存即可完成修改。

 

CSessionLocaleResolver,顾名思义,通过session会话指定语言区域,配置方式如下:

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
       <property name="defaultLocale" value="zh_CN"></property>
</bean>

 

 

DFixedLocaleResolver,固定不变的指定语言区域,不能改变。

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.FixedLocaleResolver">
        <property name="defaultLocale" value="en" />
</bean>

 

 

Spring MVC国际化Formatter支持

 

上一章讲过jdk中有三大三大格式化类:NumberFormat(数字)、MessageFormat(消息)、DateFormat(日期时间)。在String MVC国际化中,提供了对数字、日期时间处理的默认封装,也可以根据具体的业务实现自己的Formatter

 

String MVC国际化对数字支持的默认formatter如下:

NumberFormatter(已不推荐使用)NumberStyleFormatter(数字);

CurrencyFormatter(已不推荐使用)CurrencyStyleFormatter(货币);

PercentFormatter(已不推荐使用)PercentStyleFormatter(百分数)。

 

String MVC国际化对日期支持的默认formatter如下:

DateFormatter

 

直接在配置文件中配置即可使用,配置方式为:

<bean id="formatService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="org.springframework.format.number.CurrencyStyleFormatter">
                </bean>
                <bean class="org.springframework.format.number.NumberStyleFormatter">
                </bean>
                <bean class="org.springframework.format.number.PercentStyleFormatter">
                </bean>
<bean class="org.springframework.format.datetime.DateFormatter">
                </bean>
                <!--其他自定义formatters-->
            </set>
        </property>
</bean>
 
<mvc:annotation-driven conversion-service="formatService" />

 

指定mvc:annotation-driven配置,可以对MVC中的module对象进行自动转换。这里还可以配置自定义的formatters

 

自定义的formatter实现方式

 

Spring MVC自定义的formatter可以实现把String转换为指定的对象,也可以把对象转换为指定locale的字符串格式。定义自定义子类实现org.springframework.format.Formatter接口,接口申明为:

public interface Formatter<T> extends Printer<T>, Parser<T>

 

其中T为目标对象。子类必须实现其两个方法:

String print(T var1, Locale var2);
T parse(String var1, Locale var2) throws ParseException;

 

 

看一个例子:

public class LocalDateFormatter implements Formatter<LocalDate> {
 
    private DateTimeFormatter formatter;
    private String datePattern;
 
    public LocalDateFormatter(String datePattern) {
        this.datePattern = datePattern;
        formatter = DateTimeFormatter.ofPattern(datePattern);
    }
 
    @Override
    public String print(LocalDate date, Locale locale) {
        System.out.println(date.format(formatter));
        return date.format(formatter);
    }
 
    @Override
    public LocalDate parse(String s, Locale locale) throws ParseException {
        System.out.println("formatter.parse. s:" + s + ", pattern:" + datePattern);
        try {
            return LocalDate.parse(s, DateTimeFormatter.ofPattern(datePattern));
        } catch (DateTimeParseException e) {
            // the error message will be displayed in <form:errors>
            throw new IllegalArgumentException(
                    "invalid date format. Please use this pattern\""
                            + datePattern + "\"");
        }
    }
}

 

这里例子实现的是字符串与LocalDate的互转,在sprinp MVC的配置文件中添加即可:

<mvc:annotation-driven conversion-service="formatService" />
 
    <bean id="formatService"
          class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="com.sky.locale.web.controller.formatter.MyDateFormatter">
                    <constructor-arg type="java.lang.String" value="MM-dd-yyyy" />
                </bean>
            </set>
        </property>
    </bean>

 

 

Spring MVC国际化的注解支持

 

如果觉得上述配置方式使用不方便,Spring MVC还支持注解的方式对NumberDateTime提供国际化的Format支持。

 

NumberFormatAnnotationFormatterFactory

@NumberFormat注解,实现NumberString之间的解析与格式化,可以通过指定style来指示要转换的格式(Style.Number/Style.Currency/Style.Percent,当然也可以指定pattern(如pattern=#.##(保留2位小数) ),这样pattern指定的格式会覆盖掉Style指定的格式。

 

JodaDateTimeFormatAnnotationFormatterFactory

@DateTimeFormat注解,实现日期类型与String之间的解析与格式化这里的日期类型包括DateCalendarLong以及Joda的日期类型。必须在项目中添加Joda-Time包。

 

使用方法举例:

public class User {
    private String name;//姓名
 
    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date birthday;//生日
 
    @NumberFormat(style= NumberFormat.Style.CURRENCY)
    private double money;//资产
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Date getBirthday() {
        return birthday;
    }
 
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
 
    public double getMoney() {
        return money;
    }
 
    public void setMoney(double money) {
        this.money = money;
    }
}
 

 

 

到这里关于Spring MVC对国际化支持的配置和注解方式总结完毕,下一章将根据这些配置搭建一个国际化demo,整合freemaker作为展示层,并附上示例代码。

 

参考资料:《Spring 学习指南》

  • 大小: 3.3 KB
  • 大小: 9.1 KB
  • 大小: 21.7 KB
0
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics