SpringMVC输入日期与输出日期
这几天多次遇到springmvc的日期相关问题,这里总结一下以备忘。
输入日期
1、表单输入
如果是表单输入,想要springmvc将输入的日期自动映射到相应的字段上,需要以下两个步骤:
a)自定义一个日期转换类,实现org.springframework.core.convert.converter.Converter接口;
b)在springmvc相应的配置文件中声明该转换器,并注册给转换服务管理.
转换器代码:
public class CostomDateConverter implements Converter<String, Date>{
private static final List<String> formarts = new ArrayList<String>(4);
static{
formarts.add("yyyy-MM");
formarts.add("yyyy-MM-dd");
formarts.add("yyyy-MM-dd HH:mm");
formarts.add("yyyy-MM-dd HH:mm:ss");
formarts.add("HH:mm");
}
public Date convert(String source) {
String value = source.trim();
if ("".equals(value)) {
return null;
}
if(source.matches("^\\d{4}-\\d{1,2}$")){
return parseDate(source, formarts.get(0));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
return parseDate(source, formarts.get(1));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")){
return parseDate(source, formarts.get(2));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){
return parseDate(source, formarts.get(3));
}else if(source.matches("^\\d{1,2}:\\d{1,2}$")){
return parseDate(source, formarts.get(4));
}else {
throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
}
}
/**
* 功能描述:格式化日期
*
* @param dateStr
* String 字符型日期
* @param format
* String 格式
* @return Date 日期
*/
public Date parseDate(String dateStr, String format) {
Date date=null;
try {
DateFormat dateFormat = new SimpleDateFormat(format);
date = (Date) dateFormat.parse(dateStr);
} catch (Exception e) {
e.printStackTrace();
}
return date;
}
}
转换器配置:
<!-- 注册转换器 -->
<mvc:annotation-driven conversion-service="conversionService" validator="validator" ></mvc:annotation-driven>
<!-- 转换器 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.carter.test.portal.web.converter.CostomDateConverter"></bean>
</list>
</property>
</bean>
完成这两步即可将表单输入的日期成功映射到相应的字段。
2、JSON输入
有时候,数据较为复杂,所以客户端需要提交json格式的数据,也有可能包含日期格式的数据,服务器端使用@RequestBody修饰相应的POJO进行接收,这时springmvc不会使用上面form的转换器,而是使用json反序列化工具; 如果提供的日期格式不对的话,会抛出日期反序列化异常;所以可以实现一个Json反序列化接口,防止程序抛出异常,也可以定制日期的格式。
- 自定义一个类继承com.fasterxml.jackson.databind.JsonDeserializer
使用@JsonDeserialize注解修饰POJO对应的日期字段
反序列化代码
public class CustomJsonDateDeserializer extends JsonDeserializer<Date> {
private static final List<String> formarts = new ArrayList<String>(4);
static{
formarts.add("yyyy-MM");
formarts.add("yyyy-MM-dd");
formarts.add("yyyy-MM-dd HH:mm");
formarts.add("yyyy-MM-dd HH:mm:ss");
formarts.add("HH:mm");
}
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String source = jp.getText();
try {
String value = source.trim();
if ("".equals(value)) {
return null;
}
if(source.matches("^\\d{4}-\\d{1,2}$")){
return parseDate(source, formarts.get(0));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
return parseDate(source, formarts.get(1));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")){
return parseDate(source, formarts.get(2));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){
return parseDate(source, formarts.get(3));
}else if(source.matches("^\\d{1,2}:\\d{1,2}$")){
return parseDate(source, formarts.get(4));
}else {
throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 功能描述:格式化日期
*
* @param dateStr
* String 字符型日期
* @param format
* String 格式
* @return Date 日期
*/
public Date parseDate(String dateStr, String format) {
Date date=null;
try {
DateFormat dateFormat = new SimpleDateFormat(format);
date = (Date) dateFormat.parse(dateStr);
} catch (Exception e) {
e.printStackTrace();
}
return date;
}
}
POJO类对应的字段
@JsonDeserialize(using = CustomJsonDateDeserializer.class)
private Date courseBeginDate;
完成这两步即可定制Json到POJO日期字段的反序列化。
输出日期
服务器端的查询接口有时候会向客户端输出JSON格式的数据,当然包含日期格式的字段,如果springmvc使用jackson默认的格式的话,日期相关的字段的值会被格式位时间戳格式(毫秒值),但有时候客户端可能需要类似yyyy-MM-dd这样的日期格式;解决方式有多种,我常用的(比较灵活)如下:
- 在springmvc的配置文件中,注册jackson转换器,并指定输出日期的格式:(这里前提是要引入jackson相关的jar包)
<mvc:annotation-driven >
<!-- 处理responseBody 里面日期类型 -->
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd" />
</bean>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
上面的定义的输出日期转换器是全局的,如果POJO的某个日期字段不想使用这种格式输出,那么可以使用@JsonFormat注解修饰相应日期字段的getter方法,示例如下:
public class MyPojo implements java.io.Serializable{
private String id;
private Date clueUpdateDate;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id == null ? null : id.trim();
}
// 这里要指定timezone,否则时间要晚8个小时
@JsonFormat(pattern="HH:mm:ss",timezone="GMT+8")
public Date getClueUpdateDate() {
return clueUpdateDate;
}
public void setClueUpdateDate(Date clueUpdateDate) {
this.clueUpdateDate = clueUpdateDate;
}
}
下面这篇文章讲的比较详细,这里不再赘述
springmvc学习笔记–json–返回json的日期格式问题