• 数据格式化简介
  • 内建的格式转换器
  • 使用内建格式转换器示例
  • 字段级别的解析/格式化
  • 集成到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. Advapi32.dll 函数接口说明

    Advapi32.dll 函数接口说明             函数原型                               说明    AbortSystemShutDown         ...

  2. vim copy,find and replace

    VIM选择文本块/复制/粘贴 在正常模式下(按ESC进入)按键v进入可视化模式,然后按键盘左右键或h,l键即可实现文本的选择.其它相关命令:v:按字符选择.经常使用的模式,所以亲自尝试一下它. V:按 ...

  3. C#操作INI文件(明天陪你看海)

    C#操作INI文件 在很多的程序中,我们都会看到有以.ini为后缀名的文件,这个文件可以很方便的对程序配置的一些信息进行设置和读取,比如说我们在做一个程序后台登陆的时候,需要自动登录或者是远程配置数据 ...

  4. PCB MongoDb安装与Windows服务安装

    工程MI流程指示做成Web网页形式,采用MVC框架制作,数据传输用Web API方式, 最终此网页会挂到公司各系统中访问,为了提高访问并发量,并将工程数据统一结构化管理, 采用No SQL Mongo ...

  5. golang 获取statuscode

    最近日志打印的时候需要打印状态码,但是因为interface的原因直接获取失败,http.Request里面的response不知道怎么使用,所以就自己重写writeheader,write来截取st ...

  6. Python迭代器(斐波拉切数列实例)

    将一个容器通过iter()函数处理后,就变成了迭代器.迭代器有2个魔法方法__iter__.__next__,一个迭代器必须实现__iter__,这个方法实际上是返回迭代器本身(return self ...

  7. α&β测试的定义及结束的标准

    α测试在系统开发接近完成时对应用系统的测试:测试后仍然会有少量的设计变更.这种测试一般由最终用户或其他人员完成,不能由程序或测试员完成. β测试当开发和测试根本完成时所做的用例,最终的错误和问题需要在 ...

  8. JavaOO知识点小结一

    Java语言的特点是什么?简单 面向对象 跨平台 多线程 健壮性安全性 垃圾回收机制如何编译和执行java文件?产生帮助文档用什么命令?编译: javac 文件名执行: java 类名产生帮助文档 j ...

  9. https 认证总结

    https 握手阶段 服务器会下发一个证书链: 客户端默认的处理是使用系统的根证书对这个证书链进行合法性认证: 自签名证书,则需要自己完成证书链认证: 其他附属信息认证: 说白了就是一个数据检查的过程 ...

  10. java 发送http请求

    参考别人的 package test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputS ...