我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Springcloud feign传日期类型参数报错怎么办

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Springcloud feign传日期类型参数报错怎么办

这篇文章给大家分享的是有关Springcloud feign传日期类型参数报错怎么办的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

feign传日期类型参数报错

Date类型参数报错

在Spring cloud feign接口中传递Date类型参数时报错,报错信息。

场景:

客户端传递一个new Date()的参数,服务端接受的参数和客户端有时间差。

客户端打印格式化的new Date():

2018-05-11 10:23:36

而服务端接收到的参数是:

2018-05-12 00:23:36

我们从Feign启动的源码可以看出,Feign在encode和decode时会用SpringEncoder类来实现:

    @Bean    @ConditionalOnMissingBean    public Decoder feignDecoder() {        return new ResponseEntityDecoder(new SpringDecoder(this.messageConverters));    }     @Bean    @ConditionalOnMissingBean    public Encoder feignEncoder() {        return new SpringEncoder(this.messageConverters);    }

而SpringEncoder的HttpMessageConverters使用的是Jackson默认模板,该模板来自基类WebMvcConfigurationSupport.java:

Springcloud feign传日期类型参数报错怎么办

    protected final List<HttpMessageConverter<?>> getMessageConverters() {        if (this.messageConverters == null) {            this.messageConverters = new ArrayList<HttpMessageConverter<?>>();            configureMessageConverters(this.messageConverters);            if (this.messageConverters.isEmpty()) {                addDefaultHttpMessageConverters(this.messageConverters);            }            extendMessageConverters(this.messageConverters);        }        return this.messageConverters;    }

而WebMvcConfigurationSupport.java最终使用的是默认的ObjectMapper生成的MappingJackson2HttpMessageConverter。

至此可以看出该问题的产生并不是Feign的问题,而是Feign实现中使用的Spring MVC中的Jackson转换参数问题,默认的TimeZone并不是东八区,而是UTC。

        public Jackson2ObjectMapperBuilder timeZone(TimeZone timeZone) {        this.timeZone = timeZone;        return this;    }

这个问题,在Spring MVC中可以在接口或者字段上添加注解来解决,但在Feign中使用GET请求的接口添加注解是不行的。debug发现,Spring MVC在处理Date的时候,调用了sun.reflect.ConstructorAccessor#newInstance(Object[] var1),时间会加14个小时。具体实现没看到源码,后续再研究。需要说明的是,加JsonFormat注解对于Feign接口没生效,但Spring MVC是可以的。

OK,回到正题。要解决这个问题,最好的办法是自定义ObjectMapper。即使是加了注解可以解决问题,也依然推荐使用自定义ObjectMapper,因为大量的接口每个都添加注解太繁琐了。

    @Bean    @Primary    public ObjectMapper objectMapper() {        return Jackson2ObjectMapperBuilder.json()                .serializationInclusion(JsonInclude.Include.NON_NULL)                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)                .timeZone(TimeZone.getTimeZone("Asia/Shanghai"))                .build();    }

这样注解进去的ObjectMapper就带了时区。

LocalDate类型报错

报错详情:

Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not construct instance of java.time.LocalDate: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.LocalDate: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: java.io.PushbackInputStream@3ce2b1e2; line: 1, column: 44] (through reference chain: com.chunrun.user.param.UserParams["localDate"])

这是因为LocalDate没有提供默认的构造器,而Jackson还不支持Java8的特征。这时候只需要加上依赖,ObjectMapper加一行代码即可:

    <dependency>      <groupId>com.fasterxml.jackson.datatype</groupId>      <artifactId>jackson-datatype-jsr310</artifactId>      <version>2.4.0</version>    </dependency>
    @Bean    @Primary    public ObjectMapper objectMapper() {        return Jackson2ObjectMapperBuilder.json()                .serializationInclusion(JsonInclude.Include.NON_NULL)                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)                .timeZone(TimeZone.getTimeZone("Asia/Shanghai"))                .modules(new JSR310Module())                .build();    }

以上配置调用方也需要。

feign传参问题及传输Date类型参数时差的坑

feign的调用如下:

List<LeftSeatCountOfDaysResp> getLeftSeatCountOfDays(            @RequestParam("configType") Integer configType,            @RequestParam("courseId") Long courseId,            @RequestParam("startDateFrom") Date startDateFrom,            @RequestParam("startDateTo") Date startDateTo,            @RequestParam("level") Integer level);

我们采用了两个date类型的参数传参,结果:

我们传入的时间为:

Springcloud feign传日期类型参数报错怎么办

但服务端接受到的时间为:

Springcloud feign传日期类型参数报错怎么办

天啊撸,竟然出现了我们并不熟悉的14h时差,并不是我们熟悉的8个小时。feign真是天坑啊。这是SpringCloud Feign传Date类型参数的时差导致的。

备注:使用date类型传参,如果是body里面用对象传,是不会出现时差问题的。

下面说说两种解决方案

  • 当发送时间类型时,直接用String发送(推荐)

  • Feign客户端实现FeignFormatterRegistrar接口自定义DateFormatRegister

@Component    public class DateFormatRegister implements FeignFormatterRegistrar{        public DateFormatRegister(){        }        @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);            }        }    }

服务端实现:

@Configuration    public class WebConfigBeans {        @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());            }        }    }

第二种比较麻烦,但是一劳永逸,代码的优雅性比第一种好。但个人而言,还是推荐使用第一种。

feign传参时候使用@DateTimeFormat注解的坑

@NotNull    @MyFuture    @DateTimeFormat(pattern = "yyyy-MM-dd")    private Date appointDate; //预定的预成班日期

比如这个字段,服务端上面用了@DateTimeFormat注解,这样的话,springMVC手机支持直接传字符串2018-03-03自动转换的。但是,但是,如果你是用client调用,那就不报错啦,报错啦。所以使用的时候,一定要注意啊,一定要注意啊。

感谢各位的阅读!关于“Springcloud feign传日期类型参数报错怎么办”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Springcloud feign传日期类型参数报错怎么办

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Springcloud feign传日期类型参数报错怎么办

这篇文章给大家分享的是有关Springcloud feign传日期类型参数报错怎么办的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。feign传日期类型参数报错Date类型参数报错在Spring cloud fei
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录