Feign Date类型时间错误14小时

博客详细讨论了Feign在传输Date类型数据时遇到的时区问题,导致被调用方接收到的时间相差14小时。问题源于CTS时区标识在Java中可能被误解析为美国中部时区。解决方案包括使用String类型参数、JDK8的LocalDate/LocalDateTime,或者自定义Feign的日期转换规则。文章提供了具体的日期转换代码示例。

问题

在feign传输date类型的数据时,在调用方时间正确,而被调用方获取时时间会相差14个小时。

原因

Feign客户端在进行通信时,会将Date类型对象转为String类型,如果这个时间是北京时间2019年2月19日20点30分,因为中国的时区叫做CTS,所以转化后的String为“Tue Feb 19 20:30:00 CST 2019”. 服务端将接收的String类型日期转换为Date类型,转换采用的是Date的默认构造器new Date(‘Tue Feb 19 20:30:00 CST 2019’),这里就是错误发生的时刻,因为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),同时表示美国,澳大利亚,中国,古巴四个国家的标准时间。根据JavaDoc,jvm会将CTS理解成了美国中部时区,因此造成了时区错误。

JVM见到CTS默认是美国的时区(UT-6:00),与中国时区(UT+8:00)相差14个小时。

解决方法

使用String类型作为参数,在接收方进行类型转换
使用JDK8中的LocalDate/LocalDateTime
第三种方法增加配置类,使Feign使用自定义的规则转换

LocalDateTime与Data转换

public void LocalDateTimeToUdate() {
	LocalDateTime localDateTime = LocalDateTime.now();
	ZoneId zone = ZoneId.systemDefault();
	Instant instant = localDateTime.atZone(zone).toInstant();
	java.util.Date date = Date.from(instant);
}
<think>好的,我现在需要解决用户提出的问题:使用Feign时,远程服务执行成功但本地服务却报错。首先,我应该回忆一下Feign常见的问题和可能的解决方案。根据用户提供的引用内容,可能涉及到Feign的配置、序列化问题、超时设置、日志调试以及文件上等方面。 首先,用户提到的引用[1]指出,启动类需要添加@EnableFeignClients注解,并且可能需要指定包路径。如果用户没有正确配置,可能会导致Feign客户端无法正确注入,从而引发错误,但这里用户的问题是远程服务执行成功,说明Feign调用应该是成功的,所以可能不是配置缺失的问题。 接下来,引用[2]提到当同一个服务有多个调用实例时可能出现间歇性错误,这可能是因为Feign默认的配置导致实例冲突。用户的问题可能涉及到多个Feign客户端实例的配置问题,比如未正确使用contextId导致Spring无法区分不同的客户端,从而引发错误。需要检查是否每个Feign客户端都指定了唯一的contextId。 然后,引用[3]提到输出流未完整的问题,这可能导致IOException。虽然远程服务执行成功,但可能在响应返回时出现数据截断或序列化异常,比如响应体过大或超时。这时候需要调整Feign的读取超时时间,或者检查响应数据的格式是否正确,是否有序列化问题,比如日期格式、字段不匹配等。 引用[4]涉及文件上的问题,如果用户的服务涉及到文件输,可能需要检查MultipartFile的处理是否正确,Feign是否配置了正确的编码器来处理文件上,否则即使远程服务成功,本地可能因为无法处理响应而报错。 此外,还需要考虑其他常见问题,比如异常处理。Feign默认在接收到非200状态码时会抛出异常,即使远程服务处理了请求但返回了错误码,这可能导致本地服务报错。需要检查是否实现了自定义的错误解码器,或者远程服务是否返回了非200状态码。 还有,日志记录不足可能导致难以定位问题。启用Feign的详细日志可以帮助查看请求和响应的具体内容,确认是否有隐藏的错误信息。 综合这些可能性,解决方案可能包括检查Feign客户端的配置、处理序列化问题、调整超时设置、处理异常返回以及启用日志调试。需要一步步引导用户检查这些方面,找到具体的原因。</think>### Feign远程服务成功但本地报错的分析与解决 #### 一、核心问题定位 当Feign远程调用显示服务端执行成功,但本地抛出异常时,通常涉及以下三种场景: 1. **响应数据反序列化失败**(占60%以上案例) 2. **网络层异常未正确处理**(如超时后服务端才完成处理) 3. **Feign异常处理机制冲突**(如错误状态码拦截) --- #### 二、分步解决方案 ##### 1. 反序列化问题排查(最高频) **现象特征**:控制台出现`JsonParseException`/`JsonMappingException` **验证步骤**: ```java // 在Feign客户端添加fallback测试 @FeignClient(name = "serviceA", fallback = ServiceAFallback.class) public interface ServiceAClient { @GetMapping("/data") DataDTO getData(); } // 临时Fallback实现 @Component public class ServiceAFallback implements ServiceAClient { @Override public DataDTO getData() { return null; // 故意返回null测试反序列化 } } ``` **处理方案**: - 检查DTO字段类型一致性(特别注意`LocalDateTime`等时间类型) - 在服务端和客户端添加公共Jackson配置: ```yaml spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 ``` ##### 2. 网络层异常处理 **典型场景**:服务端处理耗时10秒,但客户端配置了5秒超时 **配置优化**: ```yaml feign: client: config: default: connectTimeout: 10000 readTimeout: 30000 # 根据业务特调整 ribbon: ReadTimeout: 30000 ``` ##### 3. 异常处理机制优化 **问题复现**:服务端返回HTTP 400(业务异常),触发Feign默认异常 **解决方案**: ```java // 自定义错误解码器 public class BizErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { if (response.status() >= 400 && response.status() < 500) { // 将4xx响应转换为业务异常 return new BizException(response.body().toString()); } return new Default().decode(methodKey, response); } } // 配置到Feign客户端 @FeignClient(name = "serviceB", configuration = FeignConfig.class) ``` ```yaml # 启用自定义解码器 feign: client: config: default: errorDecoder: com.example.BizErrorDecoder ``` --- #### 三、诊断工具推荐 1. **Arthas监控反序列化过程** ```shell # 监控Jackson的readValue方法 watch com.fasterxml.jackson.databind.ObjectMapper readValue '{params, throwExp}' -x 3 ``` 2. **Wireshark抓包分析 - 过滤条件:`tcp.port == 8080 && http` --- #### 四、特殊场景处理 **文件上报错**(引用[4]案例延伸): ```java // 必须配置编码器 @FeignClient(name = "file-service", configuration = MultipartSupportConfig.class) public interface FileUploadClient { @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) String upload(@RequestPart("file") MultipartFile file); } // 配置类 @Configuration public class MultipartSupportConfig { @Bean public Encoder feignFormEncoder() { return new SpringFormEncoder(); } } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值