好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

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

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

时间转换代码如下

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

/**

  * 日期格式化为字符串

  *

  * @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类型的时差问题

请看下边这段代码

?

1

2

3

4

5

6

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),同时表示美国,澳大利亚,中国,古巴四个国家的标准时间。

原因

?

1

new Date(date1.toString())

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

?

1

2

3

4

5

6

7

* <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参数的格式:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

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时的用的转化器,让转化器知道我们在客户端配置的参数格式:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

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环境中

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

原文链接:https://vegetable-chicken.blog.csdn.net/article/details/104233581

查看更多关于SpringCloud Feign 传输Date类型参数存在误差的问题的详细内容...

  阅读:19次