0061 Spring MVC的数据格式化--Formatter--FormatterRegistrar--@DateTimeFormat--@NumberFormat

Converter只完成了数据类型的转换,却不负责输入输出数据的格式化工作,日期时间、货币等虽都以字符串形式存在,却有不同的格式。

Spring格式化框架要解决的问题是:从格式化的数据中获取真正的数据,绑定数据,将处理完成的数据输出为格式化的数据。Formatter接口就是该框架最重要的接口

Converter主要是做Object与Object之间的类型转换,Formatter则是要完成任意Object与String之间的类型转换。前者适合于任何一层,而后者则主要用于web层

下面用Formatter接口完成0060中用converter完成的功能

先写个类实现Formatter接口

package net.sonng.mvcdemo.converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.springframework.format.Formatter;

public class DateFormatter implements Formatter<Date> {
    private String datePattern;
    private SimpleDateFormat dateFormat;
    public DateFormatter(String datePattern){
        this.datePattern=datePattern;
        dateFormat=new SimpleDateFormat(datePattern);
    }
    @Override
    public String print(Date date,Locale locale){
        System.out.println("Date转String类型执行中。。。。");
        return dateFormat.format(date);
    }
    @Override
    public Date parse(String source,Locale locale) throws ParseException{
        try{
            System.out.println("字符串转Date类型执行中。。。。");
            return dateFormat.parse(source);
        }catch(Exception ex){
            ex.printStackTrace();
            throw new IllegalArgumentException();
        }
    }
}

配置xml

    <mvc:annotation-driven conversion-service="conversionService" />
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!-- FormattingConversionServiceFactoryBean实现了ConversionService接口,具有类型转换和格式化的功能,既可以配置converters又可以配置formatters -->
        <property name="formatters">
            <list>
                <bean class="net.sonng.mvcdemo.converter.DateFormatter" c:_0="dd-MM-yyyy" /> <!-- 注意日期格式日-月-年 -->
            </list>
        </property>
    </bean>

访问index.html,输入数据,注意生日处按日月年的格式输入

使用FormatterRegistrar注册Formatter

要使用Formatter,除了上面的将其配置在FormattingConversionServiceFactoryBeanformatters属性中外,还可以像下面这样注册

写个类实现FormatterRegistrar

package net.sonng.mvcdemo.converter;

import org.springframework.format.FormatterRegistrar;
import org.springframework.format.FormatterRegistry;

public class MyFormatterRegistrar implements FormatterRegistrar {  //实现FormatterRegistrar接口
    private DateFormatter dateFormatter;
    
    public void setDateFormatter(DateFormatter dateFormatter) {    //setter
        this.dateFormatter = dateFormatter;
    }

    @Override
    public void registerFormatters(FormatterRegistry registry) {    
        registry.addFormatter(dateFormatter);                      //注册给定的formatter
    }
}

配置xml

    <mvc:annotation-driven conversion-service="conversionService" />
    <bean id="dateFormatter" class="net.sonng.mvcdemo.converter.DateFormatter" c:_0="dd-MM-yyyy" />   <!-- 声明formatter的bean,提供给下面的MyFormatterRegistrar -->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatterRegistrars">  <!-- 这里可以配置converters,formatters,还可以配置formatterRegistrars -->
            <set>
                <bean class="net.sonng.mvcdemo.converter.MyFormatterRegistrar" p:dateFormatter-ref="dateFormatter"  />
            </set>
        </property>
    </bean>

Spring提供的一些Formatter实现

实际上,Spring自身已经将DateFormatter写好了,位于org.springframework.format.datetime包下
另外在org.springframework.format.number包下面还提供了三个用于数字对象格式化的实现类
----NumberFormatter:用于数字类型
----CurrencyFormatter:用户货币类型
----PercentFormatter:用于百分数数字类型

用注解配置Formatter

先写个index.html,分别测试日期、整数、百分数、货币类型

<!DOCTYPE html>
<html>
<head>
    <title>Spring MVC的数据类型转换</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="resources/jquery-3.1.0.js"></script>
    <script type="text/javascript" src="resources/json2.js"></script>
    
</head>
    <body>
        <form action="register" method="post">
            日期类型:<input type="text" name="birthday" /> <br><br>
            整数类型:<input type="text" name="total" /> <br><br>
            百分数类型:<input type="text" name="discount" /><br><br>
            货币类型:<input type="text" name="money" /><br><br>
                <input type="submit" value="提交" />
        </form>
    </body>
</html>

实体类User,注解就加在该类的实例变量上

package net.sonng.mvcdemo.entity;

import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;
import org.springframework.format.annotation.NumberFormat.Style;

public class User {
    @DateTimeFormat(pattern="dd-MM-yyyy")                           //注解加在实例变量上
    private Date birthday;
    @NumberFormat(style=Style.NUMBER,pattern="#,###")               //说是这两个属性互斥,怎么可以同时出现呢?
    private int total;
    @NumberFormat(style=Style.PERCENT)
    private double discount;
    @NumberFormat(style=Style.CURRENCY)
    private double money;
    //。。。。。。。
}

controller

package net.sonng.mvcdemo.controller;

import net.sonng.mvcdemo.entity.User;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
    
    @RequestMapping("/register")
    public String register(User user,Model model){
        model.addAttribute("user", user);
        return "result";
    }
}

result.jsp

<%@page pageEncoding="utf-8" 
        contentType="text/html;charset=utf-8" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试AnnotationFormatterFactory</title>
</head>
<body>
<h3>测试表单数据格式化</h3>
<form:form modelAttribute="user" method="post" action="" >
<table>
    <tr>
        <td>日期类型:</td>
        <td><form:input path="birthday"/></td>
    </tr>
    <tr>
        <td>整数类型:</td>
        <td><form:input path="total"/></td>
    </tr>
    <tr>
        <td>百分数类型:</td>
        <td><form:input path="discount"/></td>
    </tr>
    <tr>
        <td>货币类型:</td>
        <td><form:input path="money"/></td>
    </tr>
</table>
</form:form>
</body>
</html>

输入:

输出:

org.springframework.format.annotation包下有两个注解:@DateTimeForamt和@NumberFormat

@DateTimeFormat
可以注释java.util.Date, java.util.Calendar, java.lang.Long等时间类型的变量,拥有以下三个互斥属性
----iso:类型为DateTimeFormat.ISO,常用值:
--------DateTimeFormat.ISO.DATE: 格式为yyyy-MM-dd
--------DateTimeFormat.ISO.DATE_TIME: 格式为yyyy-MM-dd hh:mm:ss .SSSZ
--------DateTimeFormat.ISO.TIME: 格式为hh:mm:ss .SSSZ
--------DateTimeFormat.ISO.NONE: 不使用ISO格式的时间
----pattern:类型为String,使用自定义的时间格式化字符串,如yyyy-MM-dd hh:mm:ss
----style:类型为String,通过样式指定日期时间的格式,由两位字符组成,第一位表示日期,第二为表示时间
--------S:短日期时间样式
--------M:中日期时间样式
--------L:长日期时间样式
--------F:完整日期时间样式
---------:(短横线)忽略日期时间样式

@NumberFormat
可注释类似数字类型的实例变量,拥有两个互斥属性
----pattern:类型String,使用自定义的数字格式化串,如##,###表示50,000
----style:类型NumberFormat.Style,几个常用值:
--------Style.CURRENCY: 货币类型
--------Style.NUMBER: 正常数字类型
--------Style.PERCENT: 百分比类型

总结

数据格式化也包含了部分数据转换的内容

实现Formatter接口,重写print()与parse()方法,实现自定义的数据格式化

Spring MVC提供了几个格式化类:DateFormatter、NumberFormatter、CurrencyFormatter、PercentFormatter

利用注解@NumberFormat和@DateTimeFormat,注释在实体类的实例变量上,也可以实现日期、时间、数字的格式化

posted @ 2017-04-03 09:27  sonng  阅读(4116)  评论(0编辑  收藏  举报