中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Springcloud?feign傳日期類型參數報錯怎么辦

發布時間:2022-03-15 09:13:28 來源:億速云 閱讀:577 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關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。

    /**
     * Override the default {@link TimeZone} to use for formatting.
     * Default value used is UTC (NOT local timezone).
     * @since 4.1.5
     */
    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傳日期類型參數報錯怎么辦”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长春市| 河间市| 临沭县| 乐业县| 彩票| 张家口市| 四会市| 巨鹿县| 无棣县| 民和| 内黄县| 江华| 五莲县| 日喀则市| 苏尼特右旗| 靖西县| 皮山县| 阜平县| 马公市| 通州市| 英山县| 清流县| 浦县| 永川市| 措美县| 宜宾市| 泸州市| 新化县| 鹤峰县| 岢岚县| 黄平县| 赣州市| 介休市| 安顺市| 安泽县| 荣昌县| 方山县| 枝江市| 当雄县| 盘山县| 常德市|