SpringCloud Feign 传输Date类型参数存在误差的问题

 更新时间:2022年03月14日 17:09:26   作者:张志翔 ̮  
这篇文章主要介绍了SpringCloud Feign 传输Date类型参数存在误差的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Feign传输Date类型参数存在误差

最近在项目开发过程中,前端传递过来的时间(Date类型)在A模块是正确的,然后A模块调用B模块将时间(Date类型)作为参数传过去,然后B模块接收到的时间有误差,天数会多一天,小时少10小时,这应该是SpringCloud Feign组件造成的问题

我这里的解决办法是在A模块调用之前先将时间(Date类型)转为String类型,B模块接收到A模块的参数后将时间由String类型再转为Date类型就可以了

时间转换代码如下

/**
 * 日期格式化为字符串
 *
 * @param source
 * @return java.lang.String
 * @author zxzhang
 * @date 2020/2/9
 */
public Date string2date(String source) throws ParseException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return sdf.parse(source);
}
 
/**
 * 字符串解析为日期
 *
 * @param source
 * @return java.lang.String
 * @author zxzhang
 * @date 2020/2/9
 */
public String date2String(Date source) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return sdf.format(source);
}

到此 Feign 传输Date类型参数存在误差的问题完美解决。

Feign传输date类型参数,时间差14个小时

Java Date类型的时差问题

请看下边这段代码

public static void main(String[] args) throws Exception {
    Date date1 = new Date();
    System.out.println("date1: " + date1.toString());
    Date date2 = new Date(date1.toString());
    System.out.println("date2: " + date2.toString());
}

执行结果如下

date1: Mon Jul 22 08:47:19 CST 2019
date2: Mon Jul 22 22:47:19 CST 2019

当前时间是2019年7月22日8点48分,CST是中国的时区China Standard Time的简称,但是可以看到date2的输入比实际时间多了14个小时。

CTS代表的时区其实有四个(Central Standard Time (USA) UT-6:00、Central Standard Time (Australia) UT+9:30、China Standard Time UT+8:00、Cuba Standard Time UT-4:00),同时表示美国,澳大利亚,中国,古巴四个国家的标准时间。

原因

new Date(date1.toString())

这个方法会调用Date.parse(String)方法,它传的参数是Mon Jul 22 08:47:19 CST 2019,这个方法上有一段注释

* <li>Any word that matches <tt>EST, CST, MST</tt>, or <tt>PST</tt>,
*     ignoring case, is recognized as referring to the time zone in
*     North America that is five, six, seven, or eight hours west of
*     Greenwich, respectively. Any word that matches <tt>EDT, CDT,
*     MDT</tt>, or <tt>PDT</tt>, ignoring case, is recognized as
*     referring to the same time zone, respectively, during daylight
*     saving time.</ul><p>

可以看到CST会被当作美国中部的时区Central Standard Time,即JVM认为你传入的时间是美国中部的时间,而当date2调用toString方法的时候,它会检测到系统的时区是中国,就会自动加14个小时(东八区与西六区的时差),就变成了Mon Jul 22 22:47:19 CST 2019

解决方法

这个问题其实如果自己写代码的话很难出现,因为所有的Java书籍都不会这么教,大多数都是通过SimpleDateFormat,进行Date和String的转换,毕竟new Date(date1.toString())这个方法已经标注为废弃了

Feign客户端的问题

Feign客户端在进行通信时,会调用Date的toString方法转为String类型,服务端在接受的时候,使用的就是new Date(String)这个方法,这里就会发生前边介绍的问题,产生14个小时的时差

解决方法

在客户端添加代码,规定Feign在将Date参数转化成String参数的格式:

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FeignFormatterRegistrar;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
 
@Slf4j
@Component
public class FeignDateFormatRegister implements FeignFormatterRegistrar {
 
    @Override
    public void registerFormatters(FormatterRegistry registry) {
        registry.addConverter(Date.class, String.class, new Date2StringConverter());
    }
 
    private class Date2StringConverter implements Converter<Date, String> {
        @Override
        public String convert(Date source) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format(source);
        }
 
    }
}

在服务端添加代码,规定SpringContext在String和Date时的用的转化器,让转化器知道我们在客户端配置的参数格式:

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
 
import javax.annotation.PostConstruct;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
@Slf4j
@Configuration
public class FeignConfiguration {
 
    @Autowired
    private RequestMappingHandlerAdapter handlerAdapter;
 
    /**
     *  增加字符串转日期的功能       
     */
    @PostConstruct
    public void initEditableValidation() {
        ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) handlerAdapter.getWebBindingInitializer();
        if (initializer.getConversionService() != null) {
            GenericConversionService genericConversionService = (GenericConversionService) initializer.getConversionService();
            genericConversionService.addConverter(String.class, Date.class, new String2DateConverter());
        }
    }
 
    class String2DateConverter implements Converter<String, Date> {
        @Override
        public Date convert(String source) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                return simpleDateFormat.parse(source);
            } catch (ParseException e) {
                log.error("", e);
            }
            return null;
        }
    }
}

注意以上两个配置类需要自己配置包扫描之类的把它们加到Spring环境中

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java使用ffmpeg实现上传视频的转码提取视频的截图等功能(代码操作)

    java使用ffmpeg实现上传视频的转码提取视频的截图等功能(代码操作)

    这篇文章主要介绍了java使用ffmpeg实现上传视频的转码,提取视频的截图等功能,本文图文并茂给大家介绍的非常详细,对大家的工作或学习具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • MyBatis之foreach标签的用法及多种循环问题

    MyBatis之foreach标签的用法及多种循环问题

    这篇文章主要介绍了MyBatis之foreach标签的用法及多种循环问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • SpringBoot Actuator监控的项目实践

    SpringBoot Actuator监控的项目实践

    本文主要结合 Spring Boot Actuator,跟大家一起分享微服务Spring Boot Actuator 的常见用法,方便我们在日常中对我们的微服务进行监控治理,感兴趣的可以了解一下
    2024-01-01
  • IDEA插件EasyCode及MyBatis最优配置步骤详解

    IDEA插件EasyCode及MyBatis最优配置步骤详解

    这篇文章主要介绍了IDEA插件EasyCode MyBatis最优配置步骤详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • 详解如何在SpringBoot中实现优雅关闭

    详解如何在SpringBoot中实现优雅关闭

    这篇文章主要介绍了如何在SpringBoot中实现优雅关闭,SpringBoot应用程序的关闭可以是崩溃,也可以是手动关闭的,Shutdown、Crash 和 Graceful 之间的区别在于,它控制决定了我们可以用这个事件做什么,本文中,一起研究下Spring Boot提供的开箱即用功能之一:优雅关闭
    2024-09-09
  • 关于@RequestParam注解的使用(简单易懂)

    关于@RequestParam注解的使用(简单易懂)

    这篇文章主要介绍了关于@RequestParam注解的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • java如何获取两个日期的时间差

    java如何获取两个日期的时间差

    这篇文章主要为大家详细介绍了java获取两个日期时间差的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • Springboot3整合Mybatis-plus3.5.3报错问题解决

    Springboot3整合Mybatis-plus3.5.3报错问题解决

    在日常学习springboot3相关的代码时,在使用 SpringBoot3 整合 MyBatisplus 时出现了一些问题,花了不少时间处理,这篇文章主要介绍了Springboot3整合Mybatis-plus3.5.3报错问题解决,需要的朋友可以参考下
    2023-11-11
  • SpringBoot 如何使用sharding jdbc进行分库分表

    SpringBoot 如何使用sharding jdbc进行分库分表

    这篇文章主要介绍了SpringBoot 如何使用sharding jdbc进行分库分表,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • springboot项目启动的时候参数无效的解决

    springboot项目启动的时候参数无效的解决

    这篇文章主要介绍了springboot项目启动的时候参数无效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09

最新评论