IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 关于SpringBoot中Swagger使用post请求传入时间类型的问题 -> 正文阅读

[Java知识库]关于SpringBoot中Swagger使用post请求传入时间类型的问题

1、问题描述

在某个功能中,后端使用@RequestBody接收前端的参数

@ApiOperation("/获取时间信息")
    @PostMapping("/getDate")
    public Object getDate(@RequestBody User user){
        System.out.println("action method: " + user.getDate().getTime());
        return user.getDate().getTime()+"";
    }

在swwager中测试接口

{
? "age": 36,
? "date": "2022-10-26 10:21:04",
? "name": "张三"
}

?实体类

@Data
public class User {
    private String name;

    private Integer age;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date date;
}

后端服务报错如下:Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2022-10-26 10:21:04": not a valid representation (error: Failed to parse Date value '2022-10-26 10:21:04': Cannot parse date "2022-10-26 10:21:04": 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 "2022-10-26 10:21:04": not a valid representation (error: Failed to parse Date value '2022-10-26 10:21:04': Cannot parse date "2022-10-26 10:21:04": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSX', parsing fails (leniency? null))<EOL> at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 3, column: 11] (through reference chain: com.prj.pojo.entity.User["date"])]?

2、代码环境:

springboot 2.6.9,java8,idea 2020.3

3、代码跟踪:

大家都知道,所有的请求后端的逻辑都会进入DispatcherServlet的doDispatch方法

逐步断点调试如下图,发现invocableMethod就是我的controller,继续断点进入

?ServletInvocableHandlerMethod的invokeAndHandle方法就是执行controller的逻辑

?

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
    // 解析参数并执行controller逻辑
	Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);
	if (returnValue == null) {
		if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
			disableContentCachingIfNecessary(webRequest);
			mavContainer.setRequestHandled(true);
			return;
		}
	}
	else if (StringUtils.hasText(getResponseStatusReason())) {
		mavContainer.setRequestHandled(true);
		return;
	}

	mavContainer.setRequestHandled(false);
	Assert.state(this.returnValueHandlers != null, "No return value handlers");
	// 处理返回值
	try {
		this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}catch (Exception ex) {
		if (logger.isTraceEnabled()){
		logger.trace(formatErrorForReturnValue(returnValue), ex);
		}
		throw ex;
	}
}

?进入invokeForRequest方法

	@Nullable
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
//解析参数
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Arguments: " + Arrays.toString(args));
		}
//执行controller方法
		return doInvoke(args);
	}

?因为是找寻解析参数失败的原因,所以进入getMethodArgumentValues方法,第179行是具体的解析逻辑,进入

?继续断点进入

?

?在下图中的for循环中的genericConverter.canRead是HttpMessageConverter的方法,用来判断能否转为java对象

?最后发现进入AbstractJackson2HttpMessageConverter类

该类也是HttpMessageConverter的子类

中间是一些判断字符集,继续断点进入

?断点进入后发现ObjectMapper是com.fasterxml.jackson.databind包下的

?一路断点到BeanDeserializer类,该方法较长,从386行到398行是一个dowhile循环

?在p变量中找到了我们在swagger中传入的参数类型,dowhile中会挨个遍历,然后转换为对应的实体类属性类型

?重点来了,当propName是date时,断点进入

?

?

?

?下图中df其实是StdDateFormat

?打开StdDateFormat类,发现仅支持这几种时间转换格式。

我在swagger传入的2022-10-26 10:21:04类型,因此直接报错

?4、解决办法:

既然找到问题了,解决也就很容易了

@Configuration
public class LocalDateTimeSerializerConfig {

    private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";

    @Bean
    public Jackson2ObjectMapperBuilder mapperBuilder() {
        Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder = new Jackson2ObjectMapperBuilder();
        jackson2ObjectMapperBuilder.dateFormat(new SimpleDateFormat(DATE_PATTERN))
                .serializerByType(LocalDateTime.class, localDateTimeSerializer())
                .deserializerByType(LocalDateTime.class, localDateTimeDeserializer());
        return jackson2ObjectMapperBuilder;
    }
    @Bean
    public LocalDateTimeSerializer localDateTimeSerializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_PATTERN));
    }

    @Bean
    public LocalDateTimeDeserializer localDateTimeDeserializer() {
        return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_PATTERN));
    }
}

?再看下图中df的值,已经变成SimpleDateFormat了,因为在上面的mapperBuilder()方法中,我指定了SimpleDateFormat和对应的解析格式。

?

?

?下面第一张图是出现转换失败时的MappingJackson2HttpMessageConverter,

第二张图是添加了LocalDateTimeSerializerConfig的MappingJackson2HttpMessageConverter,很明显,第二张图已经替换为我添加的SimpleDateFormat转换器了。

springboot的思想是约定优于配置,也就是说,springboot默认帮我们配好了spring mvc的Converter,如果我们没有自定义Converter的话,那么框架就会帮我们创建一个,如果我们有自定义的话,那么springboot就直接使用我们所注册的bean进行绑定

以上摘自https://blog.csdn.net/qq906627950/article/details/79503801

?

?

?

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 11:40:47  更:2022-10-31 11:45:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 5:01:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码