• 数据格式化简介
  • 内建的格式转换器
  • 使用内建格式转换器示例
  • 字段级别的解析/格式化
  • 集成到Spring Web MVC环境

1      数据格式化简介

对属性对象的输入/输出进行格式化,其实是属于“类型转换”的范畴。格式化转换系统是Spring通用的,其定义在org.springframework.format包中,不仅仅在Spring Web MVC场景下用。

2      内建的格式转换器

  • DateFormatter  java.util.Date<---->String,实现日期的格式化/解析
  • NumberFormatter java.lang.Number<---->String,实现通用样式的格式化/解析
  • CurrencyFormatter java.lang.BigDecimal<---->String,实现货币样式的格式化/解析
  • PercentFormatter  java.lang.Number<---->String,实现百分数样式的格式化/解析
  • NumberFormatAnnotationFormatterFactory @NumberFormat注解类型的数字字段类型<---->String

①通过@NumberFormat指定格式化/解析格式

②可以格式化/解析的数字类型:Short、Integer、Long、Float、Double、BigDecimal、BigInteger

  • JodaDateTimeFormatAnnotationFormatterFactory  @DateTimeFormat注解类型的日期字段类型<---->String

①通过@DateTimeFormat指定格式化/解析格式

②可以格式化/解析的日期类型:joda中的日期类型(org.joda.time包中的):LocalDate、LocalDateTime、LocalTime、ReadableInstant,java内置的日期类型:Date、Calendar、Long。

注意:classpath中必须有Joda-Time类库,否则无法格式化日期类型。

提示:

NumberFormatAnnotationFormatterFactory和JodaDateTimeFormatAnnotationFormatterFactory(如果classpath提供了Joda-Time类库)在使用格式化服务实现DefaultFormattingConversionService时会自动注册。

3      使用内建格式转换器示例

  • 环境准备

在示例之前,需要到http://joda-time.sourceforge.net/下载Joda-Time类库,这里使用的是joda-time-2.5版本,将这个jar包添加到项目中。

网盘下载地址:https://pan.baidu.com/s/1dGh373r

  • 类型级别的解析/格式化

一、直接使用Formatter SPI进行解析/格式化

 //CurrencyFormatter实现货币样式的格式化/解析
CurrencyFormatter currencyFormatter = new CurrencyFormatter();
//保留小数点后几位
currencyFormatter.setFractionDigits(2);
//舍入模式(CEILING表示四舍五入)
currencyFormatter.setRoundingMode(RoundingMode.CEILING);
//1、将带货币符号的字符串“$123.125”转换为BigDecimal("123.00")
BigDecimal b1 = currencyFormatter.parse("$123.125", Locale.US);
BigDecimal b2 = currencyFormatter.parse("¥123.125", Locale.CHINA);
//2、将BigDecimal("123")格式化为字符串“$123.00”展示
String s1 = currencyFormatter.print(new BigDecimal("123"), Locale.US);
String s2 = currencyFormatter.print(new BigDecimal("123"), Locale.CHINA);
System.out.println("b1="+b1+",b2="+b2+",s1="+s1+",s2="+s2);

print方法:将BigDecimal类型数据根据Locale信息格式化为字符串数据进行展示。parse方法:将带格式的字符串根据Locale信息解析为相应的BigDecimal类型数据;

不同于Convert SPI,Formatter SPI可以根据本地化(Locale)信息进行解析/格式化。

二:使用DefaultFormattingConversionService进行解析/格式化

 // DefaultFormattingConversionService 带数据格式化功能的类型转换服务实现
//DefaultFormattingConversionService会自动根据浏览器请求的信息返回相应的格式
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
//默认不自动注册任何Formatter
CurrencyFormatter currencyFormatter = new CurrencyFormatter();
currencyFormatter.setFractionDigits(2);//保留小数点后几位
currencyFormatter.setRoundingMode(RoundingMode.CEILING);//舍入模式(ceilling表示四舍五入)
//注册Formatter SPI实现
conversionService.addFormatter(currencyFormatter);
//绑定Locale信息到ThreadLocal
//FormattingConversionService内部自动获取作为Locale信息,如果不设值默认是Locale.getDefault()
//设置本地化信息到ThreadLocal,以便Formatter SPI根据本地化信息进行解析/格式化;
LocaleContextHolder.setLocale(Locale.US);
//用于将BigDecimal类型数据格式化为字符串类型
String s1 = conversionService.convert(new BigDecimal("1234.128"), String.class);
//LocaleContextHolder.setLocale(null);
LocaleContextHolder.setLocale(Locale.CHINA);
String s2 = conversionService.convert(new BigDecimal("1234.128"), String.class);
//用于将字符串类型数据解析为BigDecimal类型数据
BigDecimal b1 = conversionService.convert("¥1,234.13", BigDecimal.class);
//LocaleContextHolder.setLocale(null);
System.out.println("s1="+s1+",s2="+s2+",b1="+b1);

说明:

DefaultFormattingConversionService:带数据格式化功能的类型转换服务实现;

conversionService.addFormatter():注册Formatter SPI实现;

conversionService.convert(new BigDecimal(“1234.128”), String.class):用于将BigDecimal类型数据格式化为字符串类型,此处根据“LocaleContextHolder.setLocale(locale)”设置的本地化信息进行格式化;

conversionService.convert(“¥1,234.13”, BigDecimal.class):用于将字符串类型数据解析为BigDecimal类型数据,此处也是根据“LocaleContextHolder.setLocale(locale)”设置的本地化信息进行解;

LocaleContextHolder.setLocale(locale):设置本地化信息到ThreadLocal,以便Formatter SPI根据本地化信息进行解析/格式化;

4      字段级别的解析/格式化

前面学习了类型级别的解析/格式化,从测试用例可以看出类型级别的是对项目中的整个类型实施相的解析/格式化逻辑。

有的同学可能需要在不同的类的字段实施不同的解析/格式化逻辑,如用户模型类的注册日期字段只需要如“2013-05-02”格式进行解析/格式化即可,而订单模型类的下订单日期字段可能需要如“2013-05-02 20:13:13”格式进行展示。

这个就需要进行字段级别的解析/格式化了。

一、使用内置的注解进行字段级别的解析/格式化

1:首先准备测试用的model类

 public class FormatterModel {
@NumberFormat(style = Style.NUMBER, pattern = "#,###")
private int totalCount;
@NumberFormat(style = Style.PERCENT)
private double discount;
@NumberFormat(style = Style.CURRENCY)
private double sumMoney;
@DateTimeFormat(iso = ISO.DATE)
private Date registerDate;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date orderDate;
//省略get/set方法
}

示例说明

此处我们使用了Spring字段级别解析/格式化的两个内置注解:

1:@Number:定义数字相关的解析/格式化元数据(通用样式、货币样式、百分数样式),参数如下:

(1)style:用于指定样式类型,包括三种:Style.NUMBER(通用样式)

Style.CURRENCY(货币样式) Style.PERCENT(百分数样式),默认Style.NUMBER;

(2)pattern:自定义样式,如patter=“#,###”;

2:@DateTimeFormat:定义日期相关的解析/格式化元数据,参数如下:

(1)pattern:指定解析/格式化字段数据的模式,如”yyyy-MM-dd HH:mm:ss”

(2)iso:指定解析/格式化字段数据的ISO模式,包括四种:ISO.NONE(不使用)

ISO.DATE(yyyy-MM-dd) ISO.TIME(hh:mm:ss.SSSZ) ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ),默认ISO.NONE;

(3)style:指定用于格式化的样式模式,默认“SS”,具体使用请参考Joda-Time

类库的org.joda.time.format.DateTimeFormat的forStyle的javadoc;

优先级: pattern 大于iso 大于style。

测试代码

 //默认自动注册对@NumberFormat和@DateTimeFormat的支持
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
//准备测试模型对象
FormatterModel model = new FormatterModel();
model.setTotalCount(10000);
model.setDiscount(0.51);
model.setSumMoney(10000.13);
model.setRegisterDate(new Date(2013-1900, 4, 1));
model.setOrderDate(new Date(2013-1900, 4, 1, 20, 18, 18));
//获取类型信息
TypeDescriptor descriptor =new TypeDescriptor(FormatterModel.class.getDeclaredField("totalCount"));
TypeDescriptor stringDescriptor = TypeDescriptor.valueOf(String.class);
String s1 = (String)conversionService.convert(model.getTotalCount(), descriptor,stringDescriptor);
int a = (Integer)conversionService.convert("10,000", stringDescriptor, descriptor);
System.out.println("s1=="+s1+" , a="+a);

测试说明

1:TypeDescriptor:拥有类型信息的上下文,用于Spring3类型转换系统获取类型信息的(可以包含类、字段、方法参数、属性信息);通过TypeDescriptor,我们就可以获取(类、字段、方法参数、属性)的各种信息,如注解类型信息;

2:conversionService.convert(model.getTotalCount(), descriptor,stringDescriptor):将totalCount格式化为字符串类型,此处会根据totalCount字段的注解信息(通过descriptor对象获取)来进行格式化;

3:conversionService.convert("10,000", stringDescriptor, descriptor):将字符串“10,000”解析为totalCount字段类型,此处会根据totalCount字段的注解信息(通过descriptor对象获取)来进行解析。

继续测试,可以为不同的字段指定不同的注解信息进行字段级别的细粒度数据解析/格式化,测试如下:

 TypeDescriptor stringDescriptor = TypeDescriptor.valueOf(String.class);
TypeDescriptor descriptor = new TypeDescriptor(FormatterModel.class.getDeclaredField("registerDate"));
String s1 = (String)conversionService.convert(model.getRegisterDate(), descriptor,stringDescriptor);
Date d1 = (Date)conversionService.convert("2013-05-01", stringDescriptor, descriptor);
descriptor = new TypeDescriptor(FormatterModel.class.getDeclaredField("orderDate"));
String s2 = (String)conversionService.convert(model.getOrderDate(), descriptor,stringDescriptor);
Date d2 = (Date)conversionService.convert("2013-05-01 20:18:18", stringDescriptor,descriptor);
System.out.println("s1=="+s1+" , d1="+d1+" , s2="+s2+" , d2="+d2);

通过如上测试可以看出,我们可以通过字段注解方式实现细粒度的数据解析/格式化控制,但是必须使用TypeDescriptor来指定类型的上下文信息,即编程实现字段的数据解析/格式化比较麻烦

5      集成到Spring Web MVC环境

如果没有自定义的Formatter的话,spring的配置跟前面讲数据转换是一样的 。

测试用的Controller:

 @RequestMapping(value = "/tf")
public String testFormatter(@ModelAttribute("model") FormatterModel fm) {
LocaleContextHolder.setLocale(Locale.US);
return "formatter";
}


展示结果的formatter.jsp
,使用了两种方式

 <%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
totalCount:<spring:bind path="model.registerDate">${status.value}</spring:bind><br/>
discount:<spring:bind path="model.orderDate">${status.value}</spring:bind><br/>
sumMoney:<spring:bind path="model.sumMoney">${status.value}</spring:bind><br/>
<br/><br/>
<form:form commandName="model">
<form:input path="sumMoney"/>
</form:form>
<!-- &orderDate=1900-11-15 -->

测试用的url

在浏览器输入类似如下的url,

http://localhost:8088/05springMVC/tf?totalCount=12345&discount=0.25&sumMoney=123

就可以看到格式化后的结果了

05springMVC数据格式化的更多相关文章

  1. SpringMVC框架下数据的增删改查,数据类型转换,数据格式化,数据校验,错误输入的消息回显

    在eclipse中javaEE环境下: 这儿并没有连接数据库,而是将数据存放在map集合中: 将各种架包导入lib下... web.xml文件配置为 <?xml version="1. ...

  2. SpringMVC 数据转换 & 数据格式化 & 数据校验

    数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象 ...

  3. ECharts图表中级入门之formatter:夜谈关于ECharts图表内的数据格式化方法

    来源于:http://www.ithao123.cn/content-3751220.html 格式化之所以存在,主要是因为我们想把一些不够人性化的内容通过某种处理让其变得人性化,便于用户更好地理解内 ...

  4. PHP json数据格式化方法

    php 的json_encode能把数组转换为json格式的字符串.字符串没有缩进,中文会转为unicode编码,例如\u975a\u4ed4.人阅读比较困难.现在这个方法在json_encode的基 ...

  5. 一个通用的DataGridView导出Excel扩展方法(支持列数据格式化)

    假如数据库表中某个字段存放的值“1”和“0”分别代表“是”和“否”,要在DataGridView中显示“是”和“否”,一般用两种方法,一种是在sql中直接判断获取,另一种是在DataGridView的 ...

  6. PAT IO-04 混合类型数据格式化输入(5)

    /* *PAT IO-04 混合类型数据格式化输入(5) *2015-08-01 作者:flx413 */ #include<stdio.h> int main() { int a; fl ...

  7. IO-04. 混合类型数据格式化输入

    /** *A4-IO-04. 混合类型数据格式化输入 *C语言实现 *测试已通过 */ #include "stdio.h" int main() { float m1,m2; i ...

  8. SpringMVC(三)-- 视图和视图解析器、数据格式化标签、数据类型转换、SpringMVC处理JSON数据、文件上传

    1.视图和视图解析器 请求处理方法执行完成后,最终返回一个 ModelAndView 对象 对于那些返回 String,View 或 ModeMap 等类型的处理方法,SpringMVC 也会在内部将 ...

  9. python json.dumps()函数输出json格式,使用indent参数对json数据格式化输出

    在python中,要输出json格式,需要对json数据进行编码,要用到函数:json.dumps json.dumps() :是对数据进行编码 #coding=gbkimport json dict ...

随机推荐

  1. linux中的alsa工具与Android中的tinyalsa工具【转】

    本文转载自:http://blog.csdn.net/luckywang1103/article/details/48053015 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?) ...

  2. hdu 2602(经典01背包)

    Bone Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. UESTC--1253--阿里巴巴和n个大盗 (博弈)

     阿里巴巴和n个大盗 Time Limit: 1000MS   Memory Limit: 65535KB   64bit IO Format: %lld & %llu Submit St ...

  4. Django day15 (一) cbv装饰器 , 中间件

    一: 装饰器 二: 中间件

  5. [BZOJ2017][Usaco2009 Nov]硬币游戏(要复习系列)

    又是DP? 好吧,或者说是博弈论,但是我不会啊. 先搞个O(n^3)的记忆化搜索,然后瞎搞好像发现两个状态几乎一样? 竟然过了样例,然后竟然A了... #include<iostream> ...

  6. TCP/IP详解(三)

    超时与重传: TCP在发送一个包时,启动一个定时器,如果在定时器溢出之前没有收到ACK,则认为发出的包丢失了,此时会重传丢失的包.这就是超时重传. 其中定时器的时间不是一个固定值,它是根据RTT计算的 ...

  7. C#动态验证码

    验证码定义: 就是将一串随机产生的数字或符号,生成一幅图片,图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能 项目中,我们登录注册 ...

  8. Laravel5.1学习笔记4 控制器

    HTTP 控制器 简介 基础控制器 控制器中间件 RESTful 资源控制器 隐式控制器 依赖注入和控制器 路由缓存 简介 除了在单一的 routes.php 文件中定义所有的请求处理逻辑之外,你可能 ...

  9. Python yield解析

    Pyhton generators and the yield keyword At a glance,the yield statement is used to define generators ...

  10. 努比亚 N2(Nubia NX575J) 解锁BootLoader 并进入临时recovery ROOT

    工具下载链接:https://pan.baidu.com/s/1jJoK2Yq 备用下载链接:https://pan.baidu.com/s/1snjwLdz 密码:71rg 本篇教程教你如何傻瓜式解 ...