在系列(6)中我们介绍了如何验证提交的数据的正确性,当数据验证通过后就会被我们保存起来。保存的数据会用于以后的展示,这才是保存的价值。那么在展示的时候如何按照要求显示?(比如:小数保留一定的位数,日期按指定的格式等)。这就是本篇要说的内容—>格式化显示。

从Spring3.X开始,Spring提供了Converter SPI类型转换和Formatter SPI字段解析/格式化服务,其中Converter SPI实现对象与对象之间的相互转换,Formatter SPI实现String与对象之间的转换,Formatter SPI是对Converter SPI的封装并添加了对国际化的支持,其内部转换还是由Converter SPI完成。

下面是一个简单的请求与模型对象的转换流程:

Spring提供了FormattingConversionService和DefaultFormattingConversionService来完成对象的解析和格式化。Spring内置的几种Formatter SPI如下:

名称 功能
NumberFormatter 实现Number与String之间的解析与格式化
CurrencyFormatter 实现Number与String之间的解析与格式化(带货币符号)
PercentFormatter 实现Number与String之间的解析与格式化(带百分数符号)
DateFormatter 实现Date与String之间的解析与格式化
NumberFormatAnnotationFormatterFactory @NumberFormat注解,实现Number与String之间的解析与格式化,可以通过指定style来指示要转换的格式(Style.Number/Style.Currency/Style.Percent),当然也可以指定pattern(如pattern=“#.##”(保留2位小数) ),这样pattern指定的格式会覆盖掉Style指定的格式
JodaDateTimeFormatAnnotationFormatterFactory @DateTimeFormat注解,实现日期类型与String之间的解析与格式化这里的日期类型包括Date、Calendar、Long以及Joda的日期类型。必须在项目中添加Joda-Time包

下面就开始演示:

首先把Joda-Time包添加到之前的项目中,这里用的是joda-time-2.3.jar,在views文件夹下添加一个formattest.jsp视图,内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    money:<br/>${contentModel.money}<br/>
date:<br/>${contentModel.date}<br/>
</body>
</html>

1.首先我们直接用Formatter来做演示,在com.demo.web.models包中添加FormatModel.java内容如下:

package com.demo.web.models;

public class FormatModel{

    private String money;
private String date; public String getMoney(){
return money;
}
public String getDate(){
return date;
} public void setMoney(String money){
this.money=money;
}
public void setDate(String date){
this.date=date;
} }

在com.demo.web.controllers包中添加FormatController.java内容如下:

package com.demo.web.controllers;

import java.math.RoundingMode;
import java.util.Date;
import java.util.Locale;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.format.number.CurrencyFormatter;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.demo.web.models.FormatModel; @Controller
@RequestMapping(value = "/format")
public class FormatController { @RequestMapping(value="/test", method = {RequestMethod.GET})
public String test(Model model) throws NoSuchFieldException, SecurityException{ if(!model.containsAttribute("contentModel")){ FormatModel formatModel=new FormatModel(); CurrencyFormatter currencyFormatter = new CurrencyFormatter();
currencyFormatter.setFractionDigits(2);//保留2位小数
currencyFormatter.setRoundingMode(RoundingMode.HALF_UP);//向(距离)最近的一边舍入,如果两边(的距离)是相等的则向上舍入(四舍五入) DateFormatter dateFormatter=new DateFormatter();
dateFormatter.setPattern("yyyy-MM-dd HH:mm:ss"); Locale locale=LocaleContextHolder.getLocale(); formatModel.setMoney(currencyFormatter.print(12345.678, locale));
formatModel.setDate(dateFormatter.print(new Date(), locale)); model.addAttribute("contentModel", formatModel);
}
return "formattest";
} }

运行测试:

更改浏览器首选语言:

刷新页面:

2.这次用DefaultFormattingConversionService来做演示,把FormatController.java改为如下内容:

package com.demo.web.controllers;

import java.math.RoundingMode;
import java.util.Date;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.format.number.CurrencyFormatter;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import com.demo.web.models.FormatModel; @Controller
@RequestMapping(value = "/format")
public class FormatController { @RequestMapping(value="/test", method = {RequestMethod.GET})
public String test(Model model) throws NoSuchFieldException, SecurityException{ if(!model.containsAttribute("contentModel")){ FormatModel formatModel=new FormatModel(); CurrencyFormatter currencyFormatter = new CurrencyFormatter();
currencyFormatter.setFractionDigits(2);//保留2位小数
currencyFormatter.setRoundingMode(RoundingMode.HALF_UP);//向(距离)最近的一边舍入,如果两边(的距离)是相等的则向上舍入(四舍五入) DateFormatter dateFormatter=new DateFormatter();
dateFormatter.setPattern("yyyy-MM-dd HH:mm:ss"); DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
conversionService.addFormatter(currencyFormatter);
conversionService.addFormatter(dateFormatter); formatModel.setMoney(conversionService.convert(12345.678, String.class));
formatModel.setDate(conversionService.convert(new Date(), String.class)); model.addAttribute("contentModel", formatModel);
}
return "formattest";
} }

这次没有了Locale locale=LocaleContextHolder.getLocale();再次运行测试并更改语言后刷新,可以看到与第一种方法截图同样的效果,说明DefaultFormattingConversionService会自动根据浏览器请求的信息返回相应的格式。

3.估计有人会觉得,啊…我只是想要格式化显示而已,还要这么麻烦,写代码一个字段一个字段的转换???别急,上面只是对内置的格式化转换器做一下演示,实际项目中肯定不会这么用的,下面就介绍一下基于注解的格式化。首先把FormatModel.java改为如下内容:

package com.demo.web.models;

import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;
import org.springframework.format.annotation.NumberFormat.Style; public class FormatModel{ @NumberFormat(style=Style.CURRENCY)
   private double money;
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date date; public double getMoney(){
return money;
}
public Date getDate(){
return date;
} public void setMoney(double money){
this.money=money;
}
public void setDate(Date date){
this.date=date;
} }

注意:这里的money和date不再是String类型,而是它们自己本来的类型。

把FormatController.java改为如下内容:

package com.demo.web.controllers;

import java.util.Date;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.demo.web.models.FormatModel; @Controller
@RequestMapping(value = "/format")
public class FormatController { @RequestMapping(value="/test", method = {RequestMethod.GET})
public String test(Model model) throws NoSuchFieldException, SecurityException{
if(!model.containsAttribute("contentModel")){ FormatModel formatModel=new FormatModel(); formatModel.setMoney(12345.678);
formatModel.setDate(new Date()); model.addAttribute("contentModel", formatModel);
}
return "formattest";
} }

注意:这里代码里面只有赋值已经没有格式化的内容了。

更改视图formattest.jsp的内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body> money:<br/>
<spring:eval expression="contentModel.money"></spring:eval><br/>
date:<br/>
<spring:eval expression="contentModel.date"></spring:eval><br/> </body>
</html>

注意:这里需要添加引用<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>,并用spring:eval来绑定要显示的值。

运行测试更改浏览器语言然后刷新页面依然可以看到以第一种方法截图相同的效果,证明注解有效。

格式化显示的内容到此结束。

代码下载:http://pan.baidu.com/s/1qWM3Zf2

注: 之前没注意前11篇的示例代码,不知道为什么当时打包上传上去的是没有.project项目文件的,导致下载后不能直接导入eclipse运行,虚拟机又 被我删掉了,这些示例代码也没有备份,但是代码文件还在的,所以可以新建一个Dynamic Web Project把对应的配置文件和controller还有view导入就可以了,给大家造成的不便说声抱歉。

SpringMVC学习系列(7) 之 格式化显示的更多相关文章

  1. SpringMVC学习系列-后记 开启项目的OpenSessionInView

    在系列的 SpringMVC学习系列(12) 完结篇 的示例项目中,由于当时考虑到OpenSessionInView会对性能有一定的影响,所以就没有配置项目的OpenSessionInView.在ma ...

  2. SpringMVC学习系列-后记 解决GET请求时中文乱码的问题

    SpringMVC学习系列-后记 解决GET请求时中文乱码的问题 之前项目中的web.xml中的编码设置: <filter> <filter-name>CharacterEnc ...

  3. SpringMVC学习系列-后记 结合SpringMVC和Hibernate-validator,根据后台验证规则自动生成前台的js验证代码

    在SpringMVC学习系列(6) 之 数据验证中我们已经学习了如何结合Hibernate-validator进行后台的数据合法性验证,但是通常来说后台验证只是第二道保险,为了更好的用户体验会现在前端 ...

  4. SpringMVC学习系列(11) 之 表单标签

    本篇我们来学习Spring MVC表单标签的使用,借助于Spring MVC提供的表单标签可以让我们在视图上展示WebModel中的数据更加轻松. 一.首先我们先做一个简单了例子来对Spring MV ...

  5. SpringMVC学习系列(3) 之 URL请求到Action的映射规则

    在系列(2)中我们展示了一个简单的get请求,并返回了一个简单的helloworld页面.本篇我们来学习如何来配置一个action的url映射规则. 在系列(2)中我们在HelloWorldContr ...

  6. SpringMVC学习系列(2) 之 经典的HelloWorld实现

    前一篇简单介绍了Spring MVC的一些知识,下面就要开始学习如何把Spring MVC运用到具体的项目中去. 首先还是从一个简单的Hello World项目说起: 我机器的开发环境为: Ubunt ...

  7. SpringMVC学习系列(12) 完结篇 之 基于Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现

    到这里已经写到第12篇了,前11篇基本上把Spring MVC主要的内容都讲了,现在就直接上一个项目吧,希望能对有需要的朋友有一些帮助. 一.首先看一下项目结构: InfrastructureProj ...

  8. SpringMVC学习系列 之 表单标签

    http://www.cnblogs.com/liukemng/p/3754211.html 本篇我们来学习Spring MVC表单标签的使用,借助于Spring MVC提供的表单标签可以让我们在视图 ...

  9. SpringMVC学习系列- 表单验证

    本篇我们来学习Spring MVC表单标签的使用,借助于Spring MVC提供的表单标签可以让我们在视图上展示WebModel中的数据更加轻松. 一.首先我们先做一个简单了例子来对Spring MV ...

随机推荐

  1. 课时8—弹窗modal

    首先弹窗的实现效果如下: 主要实现的代码如下: CSS: .header,.footer,.wrap-page{ position:absolute; left:; right:; backgroun ...

  2. c# string.format json字符串 formatException错误

    正常字符串的string.format是没问题的但是在拼接json的字符串的时候因为里面包含了 {}  花括号 里面又嵌套了 {0} {1} {2}这些要替换的关键字 所以会报错. 经过百度. 字符串 ...

  3. html中input文本框,初始里边有文字提示,当点击时,文字消失,怎么设置?

    使用onfocus事件检查当前值,如果是默认值,就将value属性置空.如:<input type="text" value="请输入内容" onfocu ...

  4. POJ 3694 tarjan 桥+lca

    Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7298   Accepted: 2651 Descripti ...

  5. 使用rpm命令卸载程序

    步骤1.rpm -qa|grep 程序名称 步骤2.rpm -e 安装包名称 --nodeps

  6. 【转】搭建nginx+tomcat+Java的负载均衡环境

    一.简介: Tomcat在高并发环境下处理动态请求时性能很低,而在处理静态页面更加脆弱.虽然Tomcat的最新版本支持epoll,但是通过Nginx来处理静态页面要比通过Tomcat处理在性能方面好很 ...

  7. 团队开发——冲刺2.b

    冲刺阶段二(第二天) 1.昨天做了什么? 收集游戏图片:开始.暂停.继续.重新开始.退出……为了界面的后期美工做准备. 2.今天准备做什么? 把“开始游戏”.“退出游戏”.“取消”等文字按钮加工成游戏 ...

  8. 详解Android功耗分析工具Power Tutor的使用

    简介: PowerTutor 是由美国密歇根大学在谷歌的指导下开发的.它是用来展示google智能手机中主要组件或应用功耗的一种应用程序.例如,CPU,网络链接,LCD显示屏,GPS等.它允许开发者很 ...

  9. React Native组件之ScrollView 和 StatusBar和TabBarIos

    React Native中的组件ScrollView类似于iOS中的UIScrollView,其基本的使用方法和熟悉如下: /** * Sample React Native App * https: ...

  10. 带优先级的队列 - PHP实现

    很久以前写的一个功能,当时需要一个优先级的队列,特用新学的swoole写了一个简单的demo,仅满足当时的需求. 功能说明: 完全参考httpsqs增加优先级参数level 例:           ...