• 数据格式化简介
  • 内建的格式转换器
  • 使用内建格式转换器示例
  • 字段级别的解析/格式化
  • 集成到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. 如何使用git 生成patch 和打入patch 标签: gitpatch【转】

    本文转载自:http://blog.csdn.net/liuhaomatou/article/details/54410361 平时我们在使用git 管理项目的时候,会遇到这样一种情况,那就是客户使用 ...

  2. 2018GDOI记

    今年居然是主场.就没有游了. 向死而生.发现最近生活就是印证了我blog的那句话:就算是修罗,也会被生活玩弄于股掌间 想了很久,还是决定要继续写,然后公诸于众. ------------------- ...

  3. 清橙A1206.小Z的袜子 && CF 86D(莫队两题)

    清橙A1206.小Z的袜子 && CF 86D(莫队两题) 在网上看了一些别人写的关于莫队算法的介绍,我认为,莫队与其说是一种算法,不如说是一种思想,他通过先分块再排序来优化离线查询问 ...

  4. elasticsearch 分页查询实现方案——Top K+归并排序

    elasticsearch 分页查询实现方案 1. from+size 实现分页 from表示从第几行开始,size表示查询多少条文档.from默认为0,size默认为10,注意:size的大小不能超 ...

  5. bzoj3110 [Zjoi2013]K大数查询——线段树套线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 外层权值线段树套内层区间线段树: 之所以外层权值内层区间,是因为区间线段树需要标记下传 ...

  6. 网上订餐系统的SQL SERVER 2005数据库连接

  7. codevs2594解药还是毒药(状压dp)

    2594 解药还是毒药  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description Smart研制出对付各种症状的解药,可是 ...

  8. 关于我们ajax异步请求的方法与知识

      做前端开发的朋友对于ajax异步更新一定印象深刻,作为刚入坑的小白,今天就和大家一起聊聊关于ajax异步请求的那点事.既然是ajax就少不了jQuery的知识,推荐大家访问www.w3school ...

  9. jdbc数据库中的增删改

    HttpSession session=request.getSession(); session.setAttribute("currentUser",u.username);/ ...

  10. go的基础数据类型

    一.基础数据类型 在go语言中,数据类型用于申明函数和变量 go语言的类型 数据类型 描述 布尔型 布尔型值的只能是true 和 false ,例如 var b bool = true, 布尔型值声明 ...