Feign接⼝⽅法返回值设置⽅式
⼀、介绍
随着微服务的⼴泛应⽤,越来越多的企业都会使⽤微服务进⾏项⽬开发,在各个服务之间需要通过feign来进⾏通信,所以在feign调⽤接⼝中⽅法会接受其他服务接⼝不同类型返回值。
⼆、返回值设置
1、依据被调⽤服务接⼝设置相同返回类型
介绍:微服务A接⼝getUser 返回List<User>类型,微服务B通过feign调⽤⽅法也返回相同的结果类型。
特点:返回类型⼀⼀对应,在调⽤时不需要进⾏转化直接拿来就可以⽤。
缺点:扩展性不好,维护性不加。
解释:在⽬前springboot开发中,接⼝⼀般都会返回json类型数据(也就是使⽤@restController或者使⽤@ResponseBody注解修饰),就算是对象或者对象集合也是⼀样的,或者其他⾃⼰封装的返回对象。如果有许多不同的返回对象,当这些返回对象在A服务做了修改相应的在B服务的feign接⼝处也要做修改,相当⿇烦且不符合java⾯向接⼝编程思想。
2、全部设置为String
介绍:微服务A接⼝只要被@restController或者使⽤@ResponseBody注解修饰我统统在微服务Bfeign接⼝使⽤String来进⾏接受。
特点:通过String来接受返回参数,格式⼀致。
缺点:后⾯调⽤需要转换。
代码介绍:
// 微服务A controller 已经使⽤@restController修饰
@PostMapping(value="/getAllQuestionBank",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public List<QuestionBankDto> getAllQuestionBank(){
AllQuestionBank();
}
// 微服务B feign接⼝使⽤String进⾏接受
@PostMapping(value="/baseinfo/getAllQuestionBank")
String getAllQuestionBank();
// 微服务B 当需要调⽤feign信息时需要强转成List<QuestionBankDto>格式
// 调⽤微服务获取题库章节信息,该处强制使⽤try catch进⾏包裹
String questionBankInfo = AllQuestionBank();
List<QuestionBankDto> mysqlQuestionBank = adValue(questionBankInfo,new TypeReference<ArrayList<QuestionBankDto>>(){});
只要你导⼊⼀下springboot依赖,它默认就给你导⼊了Jackson jar包
注意事项:使⽤该⽅式时需要将ObjectMapper配置到bean容器中。
3、总结
项⽬不同,需求不同,两种⽅式没有谁对谁错之分,依据⾃⼰项⽬需求进⾏选择。
Feign 使⽤这⼏天遇到的⼀些问题
事情的起因要从我打算调⽤下paas模块服务开始
Feign 现在教程很多,然后引⼊下pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
⾃⼰定义下接⼝
@FeignClient(name = "weixinTokenClient", url = "qyapi.weixin.qq/cgi-bin")
public interface IWeiXinTokenClient {
/**
* 获取应⽤的token
* @param corpid
* @param corpsecret
* @return
*/
@RequestMapping(value = "/gettoken", method = RequestMethod.GET)
WeiXinTokenResultModel getToken(@RequestParam String corpid, @RequestParam String corpsecret);
}
写个test类测试下,完美返回,因为⾃⼰写过类似的项⽬,可以看下lemur-http,原理⼤体⼀致,想了想还是简单的.但是后⾯的问题就出来
1. nacos 配置拿不到服务
原因是:nacos注册服务只注册了lemur-admin和lemur-paas这种服务级别的服务,获取服务地址需要⽤lemur-admin服务,但是在admin调⽤paas接⼝的时候
@FeignClient(value = "paasUserFacade", contextId = "lemur-paas", path = "/im/user")
public interface IPaasUserFacade extends IBaseController<PaasUserRequestModel> {
}
@FeignClient注解不论是value,name,contextId ,serviceId全都是当做了name,所以在获取nacos地址的地⽅都是⽤paasUserFacade去匹配的,根本⽆法拿到,最终⼀直跟了N遍代码,也没有打解决办法,⾃⼰还是改了源码FeignClientFactoryBean,在注册bean的地⽅还是使⽤value ,并且不⽤contextId 注册别名,意义不⼤,还重名,把contextId 当做服务Id,feign是通过target来做地址解析的,所以只要把target的url地址改为lemur-paas/im/user就可以了
<T> T getTarget() {
FeignContext context = Bean(FeignContext.class);
Feign.Builder builder = feign(context);
if (!StringUtils.hasText(this.url)) {
if (StringUtils.tId) && !this.name.startsWith("http")){
this.url =  "" + tId;
}else if (StringUtils.tId)){
this.url =  tId;
} else if (!this.name.startsWith("http")) {
this.url = "" + this.name;
}
else {
this.url = this.name;
}
this.url += cleanPath();
return (T) loadBalance(builder, context,
new HardCodedTarget<>(pe, this.name, this.url));
}
if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
this.url = "" + this.url;
}
String url = this.url + cleanPath();
Client client = getOptional(context, Client.class);
if (client != null) {
if (client instanceof LoadBalancerFeignClient) {
// not load balancing because we have a url,
// but ribbon is on the classpath, so unwrap
reactorloadbalancerclient = ((LoadBalancerFeignClient) client).getDelegate();
}
builder.client(client);
}
Targeter targeter = get(context, Targeter.class);
return (T) targeter.target(this, builder, context,
new HardCodedTarget<>(pe, this.name, url));
}
改完源码之后,算是可以互相调⽤了
2.fastjson 不⽀持abstract class ,关键是不报错,直接返回null
因为风铃统⼀返回的都是Response对象,加泛型,结果怎么调⽤返回的都是null,看看被调⽤的服务是有收到请求并返回的,这个只能是客户端的问题了,⼀开始以为是泛型解析的问题,跟踪了整个调⽤解析链条
ReflectiveFeign.invoke->
SynchronousMethodHandler.invoke->
executeAndDecode->decode(解析对象)->
ResponseEntityDecoder.decode->
SpringDecoder.decode->
FastJsonHttpMessageConverter(真正的解析器).read(type,clazz,inputMessage)->
parseObject(is)
然后发现什么,fastjson⽆法实例化对象,我去你也报个错啊,把abstract去掉,就正常返回了
3.spring gateway 不⽀持web
spring gateway 因为使⽤webflux写的,不是web容器所以不能引⼊web,在引⼊feign的时候要把web去掉,不然起不来
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-web</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
同时spring gateway 也不⽀持读取配置⽂件,同理原因,像j2cache的⽂件配置⽅式就读取不到
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。