`

Java国际化之(五)---自定义国际化formatter注解实现

阅读更多

引言

 

由于Spring MVC自带的@NumberFormat@DateTimeFormat格式化不能很好的支持国际化,在《java国际化之---springMVC+Freemaker demo()http://moon-walker.iteye.com/blog/2379940demo中我们实现了自定的formatterMyDateFormatterMyCurrencyFormatter分别支持国际化的日期、货币处理。但有个弊端,表单对象中所有的DateBigDecimal类型都会进行相同规则的转换,不能像Spring MVC自带的@NumberFormat@DateTimeFormat对指定属性添加注解,只对指定对象进行转换。

 

庆幸的是Spring MVC支持我们对自定义的Formatter添加自己的注解。下面我们进行详细讲解,并附上demo代码,详见文章末尾Github地址。

 

自定义的Formatter注解

 

要实现自定义的Formatter注解,其实可以参考Spring MVC自带的@NumberFormat实现方法,这里我们以上一篇demo中实现的MyDateFormatter为例,进行讲解。

 

创建过程分为三步:

第一步:首先我们看下@DateTimeFormat注解在Spring MVC中的实现,并模拟创建自己的@MyDateFormat注解,内容如下:

/**
 * Created by gantianxing on 2017/6/17.
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
public @interface MyDateFormat {
 
}

 

第二步:仿照Spring MVC中的DateTimeFormatAnnotationFormatterFactory创建自己AnnotationFormatterFactory实现类MyDateFormatAnnotationFormatterFactory,内容如下:

/**
 * Created by gantianxing on 2017/6/17.
 */
public class MyDateFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<MyDateFormat> {
    private static final Set<Class<?>> FIELD_TYPES;
 
    static {
        Set<Class<?>> fieldTypes = new HashSet<Class<?>>(4);
        fieldTypes.add(Date.class);//这里只处理Date类型
        FIELD_TYPES = Collections.unmodifiableSet(fieldTypes);
    }
 
    @Override
    public Set<Class<?>> getFieldTypes() {
        return FIELD_TYPES;//返回支持的类型列表
    }
 
    @Override
    public Printer<?> getPrinter(MyDateFormat myDateFormat, Class<?> aClass) {
        return getFormatter(myDateFormat, aClass);
    }
 
    @Override
    public Parser<?> getParser(MyDateFormat myDateFormat, Class<?> aClass) {
        return getFormatter(myDateFormat, aClass);
    }
 
    protected Formatter<Date> getFormatter(MyDateFormat annotation, Class<?> fieldType) {
        MyDateFormatter formatter = new MyDateFormatter();
        return formatter;
    }
}

 

第三步:将自定义的MyDateFormatAnnotationFormatterFactory注入到spring mvc,在spring-mvc.xml中的配置代码如下:

<!-- formatter转换配置 -->
    <bean id="formatService"
          class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <!-- 采用自定义的AnnotationFormatterFactory注入,可以使用注解 -->
                <bean class="com.sky.locale.demo.formatter.factory.MyDateFormatAnnotationFormatterFactory" />
 
                <!-- 直接注入自定义Formatter无法使用注解 -->
                <bean class="com.sky.locale.demo.formatter.MyCurrencyFormatter" />
            </set>
        </property>
</bean>

 

为了对比,这里MyCurrencyFormatter没有采用自定义注解方式实现,感觉兴趣的朋友可以参照上述三个步骤自己实现。

 

使用自定义注解

 

为了方便对比,在User类中同时使用自带的@DateTimeFormat注解、自定义的@MyDateFormat注解。在上一篇代码的基础上,对birthday字段添加@DateTimeFormat注解,新增regTime字段并添加@DateTimeFormat(pattern="yyyy-MM-dd"),修改后的代码如下:

 

 

/**
 * Created by gantianxing on 2017/6/8.
 */
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @NotNull(message="{user.name.null}")
    @Size(min=2,max =5,message = "{user.name.error}")
    private String name;//姓名

    @NotNull(message="{user.birthday.null}")
    @Past(message="{user.birthday.error}")
    @MyDateFormat
    private Date birthday;//生日

    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date regDate;//注册时间

    @NotNull(message="{user.money.null}")
    @Digits(integer=3,fraction=2,message="{user.money.error}")
    @NumberFormat(pattern = "¥#.##")
    private BigDecimal money;//资产

    @NotNull(message="{user.phoneNum.null}")
    @Pattern(regexp="\\d{11}",message="{user.phoneNum.error}")
    private String phoneNum;//手机号

    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 BigDecimal getMoney() {
        return money;
    }

    public void setMoney(BigDecimal money) {
        this.money = money;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

    public Date getRegDate() {
        return regDate;
    }

    public void setRegDate(Date regDate) {
        this.regDate = regDate;
    }
}

 

启动tomcat,访问http://localhost/add页面,填写表单,Register Date的格式必须为yyyy-MM-dd,输入错误的情况下,报如下错误:



 

这种错误提示不能直接暴露给用户,我们可以通过打印器错误码,并在国际化配置文件中进行配置。比如这里的打印的错误码为:typeMismatch,在中文和英文的属性配置文件中分别配置:

typeMismatch.user.regDate=格式:yyyy-MM-dd

typeMismatch.user.regDate=Style:yyyy-MM-dd



 

 

重启tomcat,重新提交错误格式的regDate表单,显示如下:



 

 

再切换到中文ps:如果切换不成功,tomcat版本请换成tomcat8以上)



 

同时在birthday字段上使用的自定义注解@MyDateFormat,也已经生效。

 

如果在同一个表单对象中,有多个Date类型,只需要对其中部分Date字段进行自定义格式化转换,另外的采用Spring MVC默认的格式化转换,这个时候就不得不用到自定义注解实现。

 

ok 关于“自定义国际化formatter注解实现”方法讲解完毕,最后奉上代码 GitHub地址:https://github.com/gantianxing/locale-demo2.git

  • 大小: 40.5 KB
  • 大小: 25.5 KB
  • 大小: 18 KB
  • 大小: 15.6 KB
1
2
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics