05springMVC数据格式化
- 数据格式化简介
- 内建的格式转换器
- 使用内建格式转换器示例
- 字段级别的解析/格式化
- 集成到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数据格式化的更多相关文章
- SpringMVC框架下数据的增删改查,数据类型转换,数据格式化,数据校验,错误输入的消息回显
在eclipse中javaEE环境下: 这儿并没有连接数据库,而是将数据存放在map集合中: 将各种架包导入lib下... web.xml文件配置为 <?xml version="1. ...
- SpringMVC 数据转换 & 数据格式化 & 数据校验
数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象 ...
- ECharts图表中级入门之formatter:夜谈关于ECharts图表内的数据格式化方法
来源于:http://www.ithao123.cn/content-3751220.html 格式化之所以存在,主要是因为我们想把一些不够人性化的内容通过某种处理让其变得人性化,便于用户更好地理解内 ...
- PHP json数据格式化方法
php 的json_encode能把数组转换为json格式的字符串.字符串没有缩进,中文会转为unicode编码,例如\u975a\u4ed4.人阅读比较困难.现在这个方法在json_encode的基 ...
- 一个通用的DataGridView导出Excel扩展方法(支持列数据格式化)
假如数据库表中某个字段存放的值“1”和“0”分别代表“是”和“否”,要在DataGridView中显示“是”和“否”,一般用两种方法,一种是在sql中直接判断获取,另一种是在DataGridView的 ...
- PAT IO-04 混合类型数据格式化输入(5)
/* *PAT IO-04 混合类型数据格式化输入(5) *2015-08-01 作者:flx413 */ #include<stdio.h> int main() { int a; fl ...
- IO-04. 混合类型数据格式化输入
/** *A4-IO-04. 混合类型数据格式化输入 *C语言实现 *测试已通过 */ #include "stdio.h" int main() { float m1,m2; i ...
- SpringMVC(三)-- 视图和视图解析器、数据格式化标签、数据类型转换、SpringMVC处理JSON数据、文件上传
1.视图和视图解析器 请求处理方法执行完成后,最终返回一个 ModelAndView 对象 对于那些返回 String,View 或 ModeMap 等类型的处理方法,SpringMVC 也会在内部将 ...
- python json.dumps()函数输出json格式,使用indent参数对json数据格式化输出
在python中,要输出json格式,需要对json数据进行编码,要用到函数:json.dumps json.dumps() :是对数据进行编码 #coding=gbkimport json dict ...
随机推荐
- oc46--nonatomic, retain
// // Person.h #import <Foundation/Foundation.h> #import "Room.h" #import "Car. ...
- hibernate初步3
事务和并发 1.事务概念 一组不可分割的操作,事务有如下属性(ACID 属性:Atomic Consistent Isolated Durable)(1)原子性---Atomic 事务的原子性指的是 ...
- fopen文件目录问题
程序当前目录下.如果是在 VC 里面运行的, 这个目录是工程的目录. 如果是双击 exe 运行的, 这个目录就是 exe 所在的目录.
- Balloons(DFS)
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2248 题意:(1)求图中四连块(有公共边的方块 ...
- Linux<小白>详细笔记
目录 应放置的内容 /bin 系统有很多放置执行文件的目录,但是/bin目录比较特殊./bin放置的是在单用户维护模式下还能够被操作的命令.在/bin下面的命令可以被root与一般用户使用. / ...
- [BZOJ1601] 灌水
难点:找到正确方式建图 知识点:Kruskal 分析:这种题肯定要把点权转换到边权上,但肯定无法搞到和其他点相连的边上,怎么办呢?那就再造一个点呗,这个“超级点”和所有点相连,且边权=点权,于是就可以 ...
- android切换卡顿解决方法
如果想要让应用用户流畅的滑动体验的话,那么就必须对activity和fragment的生命周期有一个完整的概念以及在何种情况下会触发哪些事件. 在自己目前做的项目中,就遇到了这样的问题,那么就把自己的 ...
- HTML5 postMessage 和 localStorage 实现窗口间通信
LocalStorage(不能跨域) 基本思想:通过localStorage的标准事件storage来实现跨页面通信,即页面A通过写入特定数据触发页面B的storage事件,页面B响应之后再写入数据通 ...
- 【转】js中几种实用的跨域方法原理详解
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- Android点击跳转到淘宝的某一商品详情页或者某一店铺页面
最近项目的有个需求是点击购买资料按钮进入淘宝界面,简单分析一下,如果用户手机有淘宝就打开淘宝的页面,没有的话也可以选择使用webView进行展示,还是使用手机浏览器进行展示. 判断有无淘宝的代码就不贴 ...