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

目录
  • Feign传输Date类型参数存在误差
    • 时间转换代码如下
  • Feign传输date类型参数,时间差14个小时
    • JavaDate类型的时差问题
      • 解决方法
    • Feign客户端的问题
      • 解决方法

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

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

(0)

相关推荐

  • SpringCloud Feign参数问题及解决方法

    这篇文章主要介绍了SpringCloud Feign参数问题及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 今天遇到使用Feign调用微服务,传递参数时遇到几个问题 1.无参数 以GET方式请求 服务提供者 @RequestMapping("/hello") public String Hello(){ return "hello,provider"; } 服务消费者 @GetMapping("

  • 解决SpringCloud Feign传对象参数调用失败的问题

    SpringCloud Feign传对象参数调用失败 不支持GET请求方式 使用Apache HttpClient替换Feign原生httpclient @RequestBody接收json参数 bootstrap-local.yml feign: httpclient: enabled: true pom.xml <!-- 使用Apache HttpClient替换Feign原生httpclient --> <dependency> <groupId>com.netf

  • 详解spring cloud feign踩坑记录

    1:多客户端时,feign接口抽取到公共jar中,此时,客户端的启动类上需要对该jar中feign所在的包进行扫描,要在spring和feign中同时注册,否则启动时会报:"Consider defining a bean of type '******Feign' in your configuration." @SpringBootApplication @EnableTransactionManagement @EnableDiscoveryClient @ComponentSc

  • SpringCloud Feign多参数传递及需要注意的问题

    目录 Feign多参数传递及注意的问题 在服务提供者cloud-shop-userservice中新增几个方法 修改feign的UserService,新增对应的方法 在feign的controller中调用方法 重启修改过的服务,查看服务注册是否正常 使用工具调用这几个方法进行测试 Feign如何接收多个参数 1.API 2.Feign 3.controller Feign多参数传递及注意的问题 这边沿用前面的Eureka,Feign,Service 在服务提供者cloud-shop-user

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

    目录 Feign传输Date类型参数存在误差 时间转换代码如下 Feign传输date类型参数,时间差14个小时 JavaDate类型的时差问题 解决方法 Feign客户端的问题 解决方法 Feign传输Date类型参数存在误差 最近在项目开发过程中,前端传递过来的时间(Date类型)在A模块是正确的,然后A模块调用B模块将时间(Date类型)作为参数传过去,然后B模块接收到的时间有误差,天数会多一天,小时少10小时,这应该是SpringCloud Feign组件造成的问题 我这里的解决办法是在

  • Springcloud feign传日期类型参数报错的解决方案

    目录 feign传日期类型参数报错 Date类型参数报错 LocalDate类型报错 feign传参问题及传输Date类型参数时差的坑 下面说说两种解决方案 feign传参时候使用@DateTimeFormat注解的坑 feign传日期类型参数报错 Date类型参数报错 在Spring cloud feign接口中传递Date类型参数时报错,报错信息. 场景: 客户端传递一个new Date()的参数,服务端接受的参数和客户端有时间差. 客户端打印格式化的new Date(): 2018-05-

  • springcloud feign传输List的坑及解决

    目录 feign传输List的坑 错误方法1 错误方法2 错误方法3 feign调用传List接不到值 feign传输List的坑 无法直接传输List 错误方法1 @RequestMapping(value = "/stat/merchant/get_merchant_compare_info", method = RequestMethod.POST) @ResponseBody MerchantCompareTotalInfo getMerchantCompareInfo(  

  • SpringCloud通过Feign传递List类型参数方式

    目录 通过Feign传递List类型参数 1.单个List实体传递 2.基本类型传递 3.实体类型传递 Feign在参数为List时的坑 错误写法 正确写法 通过Feign传递List类型参数 首先明确一点,SpringCloud通过Fegin如果是多个参数,其中一个参数是List,那么是传不过去的,单个List是可以的. 1.单个List实体传递 @RequestMapping("/secret/batchInsert") public int batchInsert(@Reques

  • SpringCloud Feign如何在远程调用中传输文件

    1. 文件远程传输主要涉及3点: 请求方式, 媒体类型, 序列化与反序列化, 把握住了这3点,基本上就可以搞 2. 使用Feign传输,首先搭建起Feign的架子 2.1 引入spring-cloud-starter-eureka-server依赖,用于启动一个eureka注册中心 2.2 引入spring-cloud-starter-eureka依赖,用于开启向eureka注册中心注册自己 2.3 在调用远程服务的客户端引入spring-cloud-starter-feign, 用于使用fei

  • SpringCloud Feign转发请求头(防止session失效)的解决方案

    微服务开发中经常有这样的需求,公司自定义了通用的请求头,需要在微服务的调用链中转发,比如在请求头中加入了token,或者某个自定义的信息uniqueId,总之就是自定义的一个键值对的东东,A服务调用B服务,B服务调用C服务,这样通用的东西如何让他在一个调用链中不断地传递下去呢?以A服务为例: 方案1 最傻的办法,在程序中获取,调用B的时候再转发,怎么获取在Controller中国通过注解获取,或者通过request对象获取,这个不难,在请求B服务的时候,通过注解将值放进去即可:简代码如下: 获取

  • SpringCloud Feign实现微服务之间相互请求问题

    目录 Feign简介 Spring Cloud 组件依赖版本 Feign实现服务之间访问 ☘创建nacos-consumer-feign微服务 创建feign client ☘nacos-provider微服务 Feign微服务之间访问测试 ☘Feign容错机制 上篇文章说了通过RestTemplate实现微服务之间访问:https://www.jb51.net/article/252981.htm,这篇文章将通过Feign实现微服务之间访问.代码基于RestTemplate实现微服务之间访问基

  • 详解springcloud Feign的Hystrix支持

    本文介绍了springcloud Feign的Hystrix支持,分享给大家,具体如下: 一.Feign client中加入Hystrix的fallback @FeignClient(name="springboot-h2", fallback=HystrixClientFallback.class) //在fallback属性中指定断路器的fallback public interface UserFeignClient { // @GetMapping("/user/{i

  • 浅谈SpringCloud feign的http请求组件优化方案

    1 描述 如果我们直接使用SpringCloud Feign进行服务间调用的时候,http组件使用的是JDK的HttpURLConnection,每次请求都会新建一个连接,没有使用线程池复用.具体的可以从源码进行分析 2 源码分析 我们在分析源码很难找到入口,不知道从何开始入手,我们在分析SpringCloud feign的时候可用在配置文件下面我讲一下个人的思路. 1 首先我点击@EnableFeignClients 看一下这个注解在哪个资源路径下 如下图所示: 2 找到服务启动加载的配置文件

随机推荐