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(){
		return baseinfoQuestionMange.getAllQuestionBank();
}

// 微服务B feign接口 使用String进行接受
@PostMapping(value="/baseinfo/getAllQuestionBank")
String getAllQuestionBank();

// 微服务B 当需要调用feign信息时需要强转成List<QuestionBankDto>格式 

// 调用微服务获取题库章节信息,该处强制使用try catch进行包裹
String questionBankInfo = baseInfoApi.getAllQuestionBank();
List<QuestionBankDto> mysqlQuestionBank = objectMapper.readValue(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 = "https://qyapi.weixin.qq.com/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 = this.applicationContext.getBean(FeignContext.class);
  Feign.Builder builder = feign(context);
  if (!StringUtils.hasText(this.url)) {
   if (StringUtils.hasText(this.contextId) && !this.name.startsWith("http")){
    this.url =  "http://" + this.contextId;
   }else if (StringUtils.hasText(this.contextId)){
    this.url =  this.contextId;
   } else if (!this.name.startsWith("http")) {
    this.url = "http://" + this.name;
   }
   else {
    this.url = this.name;
   }
   this.url += cleanPath();
   return (T) loadBalance(builder, context,
     new HardCodedTarget<>(this.type, this.name, this.url));
  }
  if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
   this.url = "http://" + 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
    client = ((LoadBalancerFeignClient) client).getDelegate();
   }
   builder.client(client);
  }
  Targeter targeter = get(context, Targeter.class);
  return (T) targeter.target(this, builder, context,
    new HardCodedTarget<>(this.type, this.name, url));
 }

改完源码之后,算是可以互相调用了

2.fastjson 不支持abstract class ,关键是不报错,直接返回null

因为风铃统一返回的都是Response对象,加泛型,结果怎么调用返回的都是null,看看被调用的服务是有收到请求并返回的,这个只能是客户端的问题了,一开始以为是泛型解析的问题,跟踪了整个调用解析链条

ReflectiveFeign.invoke->
SynchronousMethodHandler.invoke->
executeAndDecode->decode(解析对象)->
ResponseEntityDecoder.decode->
SpringDecoder.decode->
HttpMessageConverterExtractor.extractData(返回泛型)->
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的文件配置方式就读取不到

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Spring Cloud Feign接口返回流的实现

    服务提供者 @GetMapping("/{id}") public void queryJobInfoLogDetail(@PathVariable("id") Long id, HttpServletResponse response) { File file = new File("xxxxx"); InputStream fileInputStream = new FileInputStream(file); OutputStream ou

  • 解决feignClient调用时获取返回对象类型匹配的问题

    feignClient调用时获取返回对象类型匹配 feignClient是springCloud体系中重要的一个组件,用于微服务之间的相互调用,底层为httpClient,在之前的应用中,我一直以为A服务提供的方法返回类型为对象的话,那么调用A服务的B服务必须也用字段类型以及命名完全相同的对象来接收,为此我验证了一下,发现不是必须用完全相同的对象来接收,比如,可以用map<String,Object>或者Object来接收,然后解析. 当然,复杂对象我还是推荐用一个完全相同的对象来接收. 下面

  • 解决feign接口返回泛型设置属性为null的问题

    简介 feign是一种声明式http请求调用方式,工作原理就是根据FeignClient注解生成新的接口(也就是传说中的动态代理),常见使用方式如下所示: @FeignClient(name="UserFeignService",url="${auth.url}", fallbackFactory = OrgFeignServiceFallback.class, configuration = FeignErrorDecoderConfiguration.class

  • 微服务之间如何通过feign调用接口上传文件

    具体需求: 我们的项目是基于springboot框架的springcloud微服务搭建的,后端服务技术层面整体上分为business服务和core服务,business服务用于作为应用层,直接连接客户端,通常用于聚合数据,core服务用来客户端具体操作不同需求来控制数据库,文件上传是通过客户端上传接口,通过business服务,由服务端调用feign接口,也是第一次做这种文件中转,遇到各种问题,下面是我自己的解决方案,不喜勿喷,代码小白一枚; 一.core服务层接口@requestmapping

  • Feign接口方法返回值设置方式

    一.介绍 随着微服务的广泛应用,越来越多的企业都会使用微服务进行项目开发,在各个服务之间需要通过feign来进行通信,所以在feign调用接口中方法会接受其他服务接口不同类型返回值. 二.返回值设置 1.依据被调用服务接口设置相同返回类型 介绍:微服务A接口getUser 返回List<User>类型,微服务B通过feign调用方法也返回相同的结果类型. 特点:返回类型一一对应,在调用时不需要进行转化直接拿来就可以用. 缺点:扩展性不好,维护性不加. 解释:在目前springboot开发中,接

  • 关于PHP通用返回值设置方法

    遇到一个不错的php代码.记录一下. 在写php代码时,经常会遇到需要返回值的情况,可以统一设置一下返回值的格式. 下面就是一个不错的例子. 配置类Return.conf.php <?php define("return_val", "return array('code' => 0, 'msg' => '', 'data' => '');"); define("RETURN_SUCCESS", 0); define(&q

  • Spring MVC处理方法返回值过程解析

    这篇文章主要介绍了Spring MVC处理方法返回值过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 对于Spring MVC处理方法支持支持一系列的返回方式: (1)ModelAndView (2)Model (3)ModelMap (4)Map (5)View (6)String (7)Void (8)Object 一,ModelAndView @RequestMapping("/threadRequest*") publi

  • django前端页面下拉选择框默认值设置方式

    1,前端样式 2,前端html代码 <select name="row.status"> <option value="ON" {% if row.status == 'ON' %} selected="selected" {% endif %}>ON</option> <option value="OFF" {% if row.status == 'OFF' %} selected=

  • Android onTouchEvent事件中onTouch方法返回值(介绍)

    1.若return false说明没有成功执行onTouch事件,在执行完onTouch里面的代码之后,onTouch事件并没有结束.因此某些组件如Gallery会自动执行它所在view里onTouch方法的代码.若在onTouch方法里面增加你的代码并且最后return false就会执行你在OnTouch方法中的处理操作了. 2.若return true说明你已经成功执行onTouch方法了,在执行完onTouch中的代码之后,这个onTouch事件就结束了.也不会再调用组件如Gallery

  • Spring实战之获取方法返回值操作示例

    本文实例讲述了Spring实战之获取方法返回值操作.分享给大家供大家参考,具体如下: 一 配置文件 <?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:

  • Vue + Axios 请求接口方法与传参方式详解

    目录 一.Get请求: 二.Post请求: 三.拓展补充 使用Vue的脚手架搭建的前端项目,通常都使用Axios封装的接口请求,项目中引入的方式不做多介绍,本文主要介绍接口调用与不同形式的传参方法. 一.Get请求: Get请求比较简单,通常就是将参数拼接到url中 用? &连接或者用下面这种方式: this.axios.get(this.getWxQyUserInfoUrl, { params: { agentid: this.doLoginParams.agentid, code: this

  • SpringMVC方法返回值多种情况代码实例

    返回ModelAndView 如果前后端不分的开发,大部分情况下,我们返回ModelAndView,即数据模型+视图: @Controller @RequestMapping("/user") public class HelloController { @RequestMapping("/hello") public ModelAndView hello() { ModelAndView mv = new ModelAndView("hello"

  • Idea 快速生成方法返回值的操作

    生成前: public static void main(String[] args) { new HashMap<String,Object>(); } 生成方法 生成后 public static void main(String[] args) { HashMap<String, Object> stringObjectHashMap = new HashMap<>(); } 快捷键: Ctrl + Alt + v 补充:idea 自动生成返回值以及返回值的类型

  • Mybatis-Plus条件构造器select方法返回指定字段方式

    目录 条件构造器select方法返回指定字段 条件构造器select用法 实例 问题解决 Mybatis-Plus修改指定字段 通用解决方案 条件构造器select方法返回指定字段 条件构造器select用法 1.返回特定的几个字段 select(字段…) 2.排除某几个字段 select(entiyClass,predicate判断) 3.分组聚合函数 select(“聚合函数”) 搭配service的.listMaps方法,将返回的数据封装到map中避免了多余字段的返回 实例 说明 :以下代

随机推荐