• 数据格式化简介
  • 内建的格式转换器
  • 使用内建格式转换器示例
  • 字段级别的解析/格式化
  • 集成到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. Spring+Mybatis之注册功能demo

    这次先注册功能的是基于登录之后,所以很多配置,实体类等就不再赘述了. 首先也不是直接在地址栏输入一个网页就可以到注册页面的.而是需要通过后台发送一个请求从而跳转到注册页面 先写注册页面,body部分 ...

  2. arm linux串口蓝牙工具移植及使用【转】

    本文转载自:http://blog.csdn.net/hclydao/article/details/51451725 p6212中串口蓝牙在linux下的使用记录 一.linux蓝牙工具移植 主要使 ...

  3. CentOS7 搭建Kafka(一)zookeeper篇

    CentOS7 搭建Kafka(一)zookeeper篇 近几年当红小生Kafka备受各路英雄好汉追捧,一点不比老前辈RabbitMQ和ActiveMQ差,因为流行,所以你就得学啊:我这么懒,肯定是不 ...

  4. python 线程池和锁

    一.死锁现象与递归锁 锁:Lock线程安全,多线程操作时,内部会让所有线程排队处理.如:list/dict/Queue        线程不安全 + 人 => 排队处理. import thre ...

  5. 最近积累的JS 东西,分享一下

    js 关闭页面 var browserName=navigator.appName; if (browserName=="Netscape") { window.open('',' ...

  6. Rabbit--ack机制

    消息应答时执行一个任务可能需要花费几秒钟,你可能会担心如果一个消费者在执行任务过程中挂掉了. 一旦RabbitMQ将消息分发给了消费者,就会从内存中删除.在这种情况下,如果正在执行任务的消费者宕机,会 ...

  7. Android Unresolved Dependencies

    在Android Studio的开发中,在软件中集成了ButterKnife插件,另外需要集成ButterKnife的jar包.因为本地没有现成的,所以在module的build.gradle文件中添 ...

  8. 关于MYSQL 存储过程的文章摘录

    1.      存储过程简介   我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储 ...

  9. IIS日志分析:SC-Status语义

    在网站属性-网站-日志(属性) 中进行设定该站点IIS日志常规属性和扩展属性,扩展属性设置IIS日志包含字段显示. HTTP协议状态(sc-status)码的含义  IIS中 100 Continue ...

  10. Interrupt中断线程

    package com.wistron.swpc.ecs.util; public class WrongWayStopThread extends Thread{ public static voi ...