项目集成openfegin
集成openfegin依赖
首先,我先跟大家说下项目的配置,整体项目使用的springboot版本为2.2.6,原生的openfegin使用的是11.0,我们通过如下方式在pom.xml中引入openfegin。
<properties> <project.build.sourceencoding>utf-8</project.build.sourceencoding> <skip_maven_deploy>false</skip_maven_deploy> <java.version>1.8</java.version> <openfegin.version>11.0</openfegin.version></properties><dependencies> <dependency> <groupid>io.github.openfeign</groupid> <artifactid>feign-core</artifactid> <version>${openfegin.version}</version> </dependency> <dependency> <groupid>io.github.openfeign</groupid> <artifactid>feign-jackson</artifactid> <version>${openfegin.version}</version> </dependency></dependencies>
这里,我省略了一些其他的配置项。
接下来,我就开始在我的项目中使用openfegin调用远程服务了。具体步骤如下。
实现远程调用
首先,创建openfeignconfig类,配置openfegin默认使用的contract。
@configurationpublic class openfeignconfig { @bean public contract usefeignannotations() { return new contract.default(); }}
接下来,我们写一个通用的获取openfeign客户端的工厂类,这个类也比较简单,本质上就是以一个hashmap来缓存所有的feginclient,这个的feginclient本质上就是我们自定义的fegin接口,缓存中的key为请求连接的基础url,缓存的value就是我们定义的feginclient接口。
public class feginclientfactory { /** * 缓存所有的fegin客户端 */ private volatile static map<string, object> feginclientcache = new hashmap<>(); /** * 从map中获取数据 * @return */ @suppresswarnings("unchecked") public static <t> t getfeginclient(class<t> clazz, string baseurl){ if(!feginclientcache.containskey(baseurl)) { synchronized (feginclientfactory.class) { if(!feginclientcache.containskey(baseurl)) { t feginclient = feign.builder().decoder(new jacksondecoder()).encoder(new jacksonencoder()).target(clazz, baseurl); feginclientcache.put(baseurl, feginclient); } } } return (t)feginclientcache.get(baseurl); }}
接下来,我们就定义一个feginclient接口。
public interface feginclientproxy { @headers("content-type:application/json;charset=utf-8") @requestline("post /user/login") userloginvo login(userloginvo loginvo);}
接下来,我们创建springboot的测试类。
@runwith(springrunner.class)@springboottestpublic class icpsweightstartertest { @test public void testuserlogin() { responsemessage result = feginclientfactory.getfeginclient(feginclientproxy.class, "http://127.0.0.1").login(new userloginvo("zhangsan", "123456", 1)); system.out.println(jsonutils.bean2json(result)); }}
一切准备就绪,运行测试。麻蛋,出问题了。主要的问题就是通过openfeign请求返回值localdatetime字段会发生异常!!!
注:此时异常时,我们在localdatetime字段上添加的注解如下所示。
import java.time.localdatetime;import com.baomidou.mybatisplus.annotation.fieldfill;import com.baomidou.mybatisplus.annotation.tablefield;import com.fasterxml.jackson.annotation.jsonformat;@tablefield(value = "create_time", fill = fieldfill.insert)@jsonformat(pattern = "yyyy-mm-dd hh:mm:ss", locale = "zh", timezone = "gmt+8")private localdatetime createtime;
解决问题
问题描述
springboot通过原生openfeign客户端调用http接口,如果返回值中包含localdatetime类型(包括其他jsr-310中java.time包的时间类),在客户端可能会出现反序列化失败的错误。错误信息如下:
caused by:com.fasterxml.jackson.databind.exc.invaliddefinitionexception: cannot construct instance of `java.time.localdatetime` (no creators, like default construct, exist): no string-argument constructor/factory method to deserialize from string value ("2020-10-07t11:04:32")
问题分析
从客户端调用fegin,也是相当于url传参就相当于经过一次json转换,数据库取出‘2020-10-07t11:04:32"数据这时是时间类型,进过json之后就变成了string类型,t就变成了字符不再是一个特殊字符,因此string的字符串“2020-10-07t11:04:32”反序列化就会失败。
问题解决
在项目中增加依赖。
<dependency> <groupid>com.fasterxml.jackson.datatype</groupid> <artifactid>jackson-datatype-jsr310</artifactid> <version>2.9.9</version></dependency>
注:如果是用的是springboot,并且明确指定了springboot版本,引入jackson-datatype-jsr310时,可以不用指定版本号。
接下来,在pojo类的localdatetime类型字段增加如下注解。
import com.fasterxml.jackson.databind.annotation.jsondeserialize;import com.fasterxml.jackson.datatype.jsr310.deser.localdatetimedeserializer;
添加后的效果如下所示。
import java.time.localdatetime;import com.baomidou.mybatisplus.annotation.fieldfill;import com.baomidou.mybatisplus.annotation.tablefield;import com.fasterxml.jackson.annotation.jsonformat;import com.fasterxml.jackson.databind.annotation.jsondeserialize;import com.fasterxml.jackson.datatype.jsr310.deser.localdatetimedeserializer;@tablefield(value = "create_time", fill = fieldfill.insert)@jsonformat(pattern = "yyyy-mm-dd hh:mm:ss", locale = "zh", timezone = "gmt+8")@jsondeserialize(using = localdatetimedeserializer.class)private localdatetime createtime;
此时,再次调用远程接口,问题解决。
以上就是springboot整合openfeign的坑怎么解决的详细内容。