springcloud 入门系列Feign(声明式服务调用)

2022-07-23 09:56:39

前面我们学习了eureka 服务的搭建,以及ribbon,hystrx,分布式开发中很重要的两个功能组件,负载均衡和服务熔断机制来对我们的微服务进行保护。

前面我们在进行eureka 服务进行调用时都是采用RestTemplate 进行封装http服务调用,形成了一套模板的调用方法,实际应用当中,某个我服务提供的服务接口会被我们在多处调用,这时候我们往往会自己封装服务的调用客户端。而springcloud 也为我们提供了这样的服务客户端封装组件-Fegin,

他提供了声明式服务的调用。

下面我们开始动手实践;

新建使用Feign 声明式服务调用的客户端,以后代码只贴出核心相关代码,否则会导致文章篇幅太长,文章被代码所充斥。

pom:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.3.RELEASE</version>
        </dependency>

声明服务:

@FeignClient("HELLOSERVICE")public interface HelloService {    @GetMapping("hello")    String hello(@RequestParam String name);}

@FeignClient("HELLOSERVICE")这里 声明了 helloService 服务,注解中的参数名称就是eureka中注册的服务名称,注意这里服务名不区分大小写,建议直接从eureka服务注册中心拷贝。然后我们使用了springmvc 自带的注解@GetMapping进行需要调用的方法声明。

controller:

@RestControllerpublic class Controller {    @Autowired    private HelloService helloService;    @GetMapping("feign-hello")    private String test(@RequestParam String name){        return  helloService.hello(name);    }}

springboot 引导类:

@FeignClient("HELLOSERVICE")
public interface HelloService {

    @GetMapping("hello")
    String hello(@RequestParam String name);

}

@EnableFeignClients 开启feigin声明式服务。

下面我们启动服务,并在浏览器输入:http://localhost:8088/feign-hello?name=alibb

查看输出:

https://mmbiz.qpic.cn/mmbiz_png/StSSauj2rMpUS1b5V8LMILiaicGcT4aeKhmRrpc8Fmqv6nUAIWWDlDibKKrOu2aMQia2B70LIXBesc51Foic400zHQQ/640?wx_fmt=png

我们看到了服务器返回了预期的响应。

不过这里有个小坑点,这里做小说明,我们在进行url传值时,我们的服务提供者和Feign 声明的接口中都必须加@RequestParam注解,否则会爆出405错误。但是我们知道 springmvc 中url传值,不是必须制定@RequestParam注解的,框架自动能够匹配参数。笔者不知道是Feign 作者故意为之还是有其他的考量。

下面我们来介绍下Fegin 的继承特性,我们发现Feign 的客户端代码几乎可以直接从服务实现中复制过来,是否可以进一步进行抽象呢,springcloud Feign 针对此项问题进行了抽象。为了复用接口和 DTO ,我们新建一个helloApi 工程:

pom:

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

请求接口定义:

@RequestMapping("refact")
public interface HelloServiceApi {


    @RequestMapping("/hello1")
    String hello1(@RequestParam String name);

    @PostMapping("/hello2")
    String hello2(@RequestBody User user);

}

DTO定义:

@Data
public class User {
    private String name;
    private Integer age;
}

我们看到这个就是一个请求api 的定义,没有任何特殊之处,下面我们进行服务提供者的修改:

首先引入api的pom依赖:

<dependency>
            <groupId>com.ethan.springclod.api</groupId>
            <artifactId>api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

新建一个Controller 并实现上述接口:

@RestController
@Slf4j
public class HelloFeignController implements HelloServiceApi {
    @Override
    public String hello1(String name) {
        log.info("feign hello1:{}" ,name);
        return "hello world " + name;
    }

    @Override
    public String hello2(User user) {
        log.info("feign hello2:{}" ,user);
        return user.toString();
    }
}

然后启动服务。

在服务调用端我们也作出调整,在pom中同样添加helloservice 的api 依赖,然后创建RefactHelloService:

@FeignClient("HELLOSERVICE")
public interface RefactHelloService extends HelloServiceApi {

}

controller 调整:

    @Autowired
    private RefactHelloService helloServiceApi;

    @GetMapping("feign-hello")
    private String test(@RequestParam String name){
        return  helloServiceApi.hello1(name);
    }


    @GetMapping("feign-hello3")
    private String test3(){
        User user = new User();
        user.setName("ethan");
        user.setAge(28);
        return  helloServiceApi.hello2(user);
    }

然后我们启动服务发送请求测试:http://localhost:8088/feign-hello3

https://mmbiz.qpic.cn/mmbiz_png/StSSauj2rMpUS1b5V8LMILiaicGcT4aeKhMgSHUz5xf7zKUP2XUqJlBSibFiaibzHfo6K3DDMCWgzpr7XnpZicic8icRDQ/640?wx_fmt=png

https://mmbiz.qpic.cn/mmbiz_png/StSSauj2rMpUS1b5V8LMILiaicGcT4aeKhPfZKXibh5tMyAMd4YYpDLeZ4FCRvjKIZ7P8hVsIchGB5W3MJ7e80agA/640?wx_fmt=png

看到对应的返回和控制台输出,一切正常。

由此,我们可以通过对外封装api,给调用者调用,可以提高我们的开发效率。

本篇关于Feign 介绍到此结束,如有不对之处,欢迎指正!

  • 作者:feijiing
  • 原文链接:https://blog.csdn.net/feijiing/article/details/100034385
    更新时间:2022-07-23 09:56:39