color2Rain 2020-04-17 13:40 采纳率: 0%
浏览 1485

Feign接口继承抽离出公共方法,如何实现将服务端的公共代码抽离出来

使用feign接口时遇到的问题

现在有三个应用,消费端,服务端,接口端

API端

@RequestMapping("/shop-member")
public interface LibrarianApi{
    @RequestMapping(value = "/getByName", method = RequestMethod.GET)
    public Result<ShopMemberDTO> getByName(@RequestParam("name") String name);
}

消费端

@FeignClient(name = "librarian")
public interface ShopMemberApi extends ShopMemberLibrarianApi{
}

服务端

@RestController
public class ShopMemberNewController implements ShopMemberLibrarianApi {

}
  • 服务端和消费端都实现继承了API端的接口,在API端定义了请求路径,上述情况下分别启动应用,消费端调用正常。

  • 现在想将服务端的部分代码抽离出来,改成下面的形式

@RestController
public class ShopMemberNewController extends BaseController<ShopMemberDTO>  implements ShopMemberLibrarianApi {

}

BaseController中是抽离的公共方法,可是现在消费端无法找到服务端的接口
,404错误。

  • 写回答

1条回答 默认 最新

  • qq_42914371 2020-04-17 16:40
    关注

    技术需求点:
    在SpringCloud部署的微服务系统中,消费者通过Feign组件调用提供者的微服务。
    一.Feign简介
    在前文SpringCloud+SpringBoot搭建服务注册与调用平台中,我们使用了Ribbon客户端实现了微服务之间的调用,Ribbon本身集成了负载均衡的功能,但是Ribbon有一个使用不便的地方:每次使用需要手动拼接请求的url,还要对返回的结果进行格式化处理。为了解决这个不便,SpringCloud提供了一个声明式的调用组件:Feign,它可以帮助我们便捷的调用注册在注册中心的微服务。
    Feign是一种声明式调用组件,提供了一种基于接口的编程方式,我们只要声明接口并配置注解,SpringCloud会根据配置以Rest风格的方式从其它微服务系统中调用方法并获取数据。
    主要有以下几个优点:
    (1)可插拔的注解支持,包括Feign注解和JAX-RS注解;
    (2)支持可插拔的HTTP编码器和解码器;
    (3)支持Hystrix和它的Fallback;
    (4)支持Ribbon的负载均衡,如果某个微服务id下有两个端口提供2个同样的服务,会采用轮询机制调用;
    (5)支持HTTP请求和相应的压缩。
    https://segmentfault.com/a/1190000019685780?utm_source=tag-newest
    二.工程搭建
    在之前的文章中,我们已经搭建好了基于Springcloud + SpringBoot的工程结构:springcloud-eureka-server、springcloud-eureka-provider、springcloud-eureka-consumer等角色,这次只需要在springcloud-eureka-provider中将Ribbon组件调用的方式改成Feign即可。
    1.pom文件中添加Feign依赖

    org.springframework.cloud
    spring-cloud-starter-openfeign

    我之前使用的版本:Spring Boot版本:1.5.3.RELEASE,Spring Cloud版本:Dalston.SR5。
    添加feign的pom依赖之后,发现找不到用于负载均衡的LoadBalancedRetryFactory的包,上网查资料发现是SprongBoot和SpringCloud的版本问题,不是所有SpringBoot和SpringCloud的包都是兼容的,两者的版本必须匹配使用,官网上两者匹配的版本如下:

    image.png

    因此,我们项目中SpringBoot版本改为用:2.0.3.RELEASE,SpringCloud的版本改为用:Finchley.RELEASE,改动代码如下:

    org.springframework.boot
    spring-boot-starter-parent
    2.0.3.RELEASE

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    

    2.目录结构

    image.png
    3.创建UserFeignService接口
    Feign只需要写一个接口,在接口配置好需要调用的微服务id,并声明接口即可。如代码所示,使用注解@FeignClient,"eureka-provider"是提供者的serviceid,在整个微服务系统中是唯一的,表明该接口将调用eureka-provider的服务。方法名称和返回类型直接copy被调用服务的方法即可。
    //开启feign客户端,eureka-provider-user微服务的serviceid(唯一)
    @FeignClient("eureka-provider")
    public interface UserFeignService {
    @RequestMapping("/user")
    public List getUsers();
    }

    @RequestMapping要写完整路径。我们这里路径比较简单,直接是"/user",如果原服务的路径是下面这种,就需要写成"/provider/user"

    image.png
    4.修改启动类
    启动类上添加@EnableFeignClients开启Feign客户端。
    @EnableFeignClients//开启Feign客户端
    @EnableEurekaClient//开启Eureka客户端
    @SpringBootApplication
    public class EurekaApplication {
    public static void main(String[] args) {
    SpringApplication.run(EurekaApplication.class,args);
    }
    }

    三.测试结果
    依次启动springcloud-eureka-server(集群)、springcloud-eureka-provider、springcloud-eureka-consumer服务,启动成功后,查看控制台http://192.168.33.100:8761

    image.png
    输入http://127.0.0.1:9091/consumer,看到下列返回说明调用成功!

    image.png

    四.扩展
    Feign还有另外一种继承与实现的使用方式,大概做法是抽离出一个公共API项目,写一个接口让消费者继承,实现方法在提供者中实现,调用该公共接口的方法即可。
    这种做法的好处是创建了独立的api项目,可以很方便的实现接口定义和依赖共享,不用再复制粘贴接口,但弊端是增加了服务提供者和消费者之间的耦合,如果服务提供者修改了一个接口定义,消费者也得跟着变,进而带来一些坑。
    有兴趣的同学可以参考:https://www.jianshu.com/p/ff79509b0962

    作者:superxcp
    链接:https://www.jianshu.com/p/df5aa32f42a0
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    评论

报告相同问题?

悬赏问题

  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3