客户端传日期格式字段(String),服务端接口使用java.util.Date类型接收报错问题

客户端传日期格式字段(string),服务端接口使用java.util.Date类型接收报错问题

问题演示

  1. 演示代码

服务端接口代码

java 复制代码
	@PostMapping("/binder")
	@ResponseBody
	public String binderTest(TestEntity te) {
		return te.getBirthDay().toString() ;
	}

以上接口中的实体TestEntity

java 复制代码
import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;

import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.Data;

@Data
public class TestEntity {

	private String name;
	
	private String addr;
	
	private Date birthDay;
}

TestEntity中的字段birthDay为Date类型

客户端演示使用PostMan

第1种:客户端以URL拼接的方式传值


后台报错:

Field error in object 'testEntity' on field 'birthDay': rejected value [2024-02-09 22:22:33]; codes 
[typeMismatch.testEntity.birthDay,typeMismatch.birthDay,typeMismatch.java.util.Date,typeMismatch]; 
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes 
[testEntity.birthDay,birthDay]; arguments []; default message [birthDay]]; default message [Failed to convert 
property value of type 'java.lang.String' to required type 'java.util.Date' for property 'birthDay'; nested exception 
is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] 
to type [java.util.Date] for value '2024-02-09 22:22:33'; nested exception is 
java.lang.IllegalArgumentException]]

第2种:客户端以body中的form-data方式提交


后台报错:

Field error in object 'testEntity' on field 'birthDay': rejected value [2024-02-07]; codes 
[typeMismatch.testEntity.birthDay,typeMismatch.birthDay,typeMismatch.java.util.Date,typeMismatch]; 
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes 
[testEntity.birthDay,birthDay]; arguments []; default message [birthDay]]; default message [Failed to convert 
property value of type 'java.lang.String' to required type 'java.util.Date' for property 'birthDay'; nested exception 
is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] 
to type [java.util.Date] for value '2024-02-07'; nested exception is java.lang.IllegalArgumentException]]

第3种 客户端以Body中的json方式提交

这里需要先在接口中,添加注解@RequestBody,接口变成如下:

java 复制代码
	@PostMapping("/binder")
	@ResponseBody
	public String binderTest(@RequestBody TestEntity te) {
		return te.getBirthDay().toString() ;
	}


以上日期格式是 yyyy-MM-dd (2024-06-08),可以成功!
但是,将格式变成yyyy-MM-dd HH:mm:ss,就不行了,见如下:

后台报错:

JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2024-06-08 22:11:33": not a 
valid representation (error: Failed to parse Date value '2024-06-08 22:11:33': Cannot parse date "2024-06-08 
22:11:33": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSX', parsing fails (leniency? null)); nested 
exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type 
`java.util.Date` from String "2024-06-08 22:11:33": not a valid representation (error: Failed to parse Date value 
'2024-06-08 22:11:33': Cannot parse date "2024-06-08 22:11:33": while it seems to fit format 'yyyy-MM-
dd'T'HH:mm:ss.SSSX', parsing fails (leniency? null))
 at [Source: (PushbackInputStream); line: 2, column: 16] (through reference chain: 

问题解决(全局解决方式)

针对 第1和第2种情况

解决办法

新增日期转换类,并将其纳入到spring的bean管理中:

java 复制代码
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.core.convert.converter.Converter;

/**
 * 日期格式转换类,
 * 
 * 仅针对当客户端是以下两种方式日期格式值的转换
 * 
 * 1.url地址拼接的方式,形如:localhost:8031/binder?birthDay=2024-02-09 22:22:33。
 * 
 * 2.body方式中的form-data方式!
 * 
 * 注意!!!与DateJacksonConverter类区别。
 * 
 * @author Administrator
 */
public class MyDateConverter implements Converter<String, Date> {

	// TODO 2024年4月12日16:01:01
	// 完善---日期格式有多种这里只列举了一种,根据传入的String格式日期分别初始化SimpleDateFormat,还有如下格式需要处理:
	//private static String[] pattern = new String[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss",
	//		"yyyy-MM-dd HH:mm:ss.S", "yyyy.MM.dd", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss.S",
	//		"yyyy/MM/dd", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss.S" };

	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	@Override
	public Date convert(String s) {
		Date date = null;
		try {
			date = sdf.parse(s);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
		return date;
	}
}
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 配置数据绑定
 * 
 * @author Administrator
 *
 */
@Configuration
public class MyConfigurableWebBindingInitializer {

	/**
	 * 仅针对当客户端是以下两种方式日期格式值的转换
	 * 1.url地址拼接的方式,形如:localhost:8031/binder?birthDay=2024-02-09 22:22:33。
	 * 2.body方式中的form-data方式!
	 * 
	 * @return
	 */
	@Bean
	public MyDateConverter myDateConverter() {
		return new MyDateConverter();
	}
}

验证



均成功!

针对第3中情况

解决办法

同样,新增日期转换类,并将其纳入到spring的bean管理中:

java 复制代码
import java.io.IOException;
import java.text.ParseException;
import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

/**
 * 日期格式转化类:
 * 
 * 针对客户端传值方式为 body中的json方式
 * 
 * 注意!!!与MyDateConverter类区别。
 * 
 * @author Administrator
 * 
 * https://www.jianshu.com/p/c97a20fc9a35
 *
 */
public class DateJacksonConverter extends JsonDeserializer<Date> {
	private static String[] pattern = new String[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss",
			"yyyy-MM-dd HH:mm:ss.S", "yyyy.MM.dd", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss.S",
			"yyyy/MM/dd", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss.S" };

	@Override
	public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {

		Date targetDate = null;
		String originDate = p.getText();
		if (StringUtils.isNotEmpty(originDate)) {
			try {
				long longDate = Long.valueOf(originDate.trim());
				targetDate = new Date(longDate);
			} catch (NumberFormatException e) {
				try {
					targetDate = DateUtils.parseDate(originDate, DateJacksonConverter.pattern);
				} catch (ParseException pe) {
					throw new IOException(String.format(
							"'%s' can not convert to type 'java.util.Date',just support timestamp(type of long) and following date format(%s)",
							originDate, StringUtils.join(pattern, ",")));
				}
			}
		}
		return targetDate;
	}

	@Override
	public Class<?> handledType() {
		return Date.class;
	}
}
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 配置数据绑定
 * 
 * @author Administrator
 *
 */
@Configuration
public class MyConfigurableWebBindingInitializer {

	/**
	 * 仅针对当客户端是以下两种方式日期格式值的转换
	 * 1.url地址拼接的方式,形如:localhost:8031/binder?birthDay=2024-02-09 22:22:33。
	 * 2.body方式中的form-data方式!
	 * 
	 * @return
	 */
	@Bean
	public MyDateConverter myDateConverter() {
		return new MyDateConverter();
	}

	// ======针对客户端传值方式为 body中的json方式:对日期格式进行转换======开始
	@Bean
	public DateJacksonConverter dateJacksonConverter() {
		return new DateJacksonConverter();
	}

	@Bean
	public Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean(
			@Autowired DateJacksonConverter dateJacksonConverter) {
		Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean();

		jackson2ObjectMapperFactoryBean.setDeserializers(dateJacksonConverter);
		return jackson2ObjectMapperFactoryBean;
	}

	@Bean
	public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
			@Autowired ObjectMapper objectMapper) {
		MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
		mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
		return mappingJackson2HttpMessageConverter;
	}
	// ======针对客户端传值方式为 body中的json方式======结束

}

验证

需给接口加上@RequestBody注解,略。

成功!