SpringCloud学习--- Feign详解(附代码压缩包)

Posted 小样5411

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud学习--- Feign详解(附代码压缩包)相关的知识,希望对你有一定的参考价值。

前言

上一篇:Ribbon详解
Feign是什么?它是一种可以帮助我们实现面向接口编程,直接在本服务中非常简单的调用其他服务,简化开发,从Eureka复杂配置,到Ribbon,再到Feign,新的组件会让开发更简单,下面直接演示,没学过前两个的看看我之前两篇文章,案例都是层层递进的

一、Feign初步实战

同样完成上一节Ribbon效果,用Feign会更简单
第一步:
在eureka_client_customer的pom.xml中导入Feign依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

第二步:
启动类添加@EnableFeignClients注解

第三步
创建接口,这里创建PayClient

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient("payClient")   //写服务名称 可以找到其他目标服务
public interface PayClient {
	
	//目标服务是什么内容就套上去写一样的,然后访问此处pay就能调用到payClient服务的pay方法,优点重写的意思
    @RequestMapping(value = "/pay",method = RequestMethod.GET) 
    String pay();   //支付服务的pay方法
}

第四步:
CustomerController中用Feign方式调用,这里相比用Eureka、Ribbon更干净了,只有一点点,用一个接口就能访问到pay服务

@RestController
public class CustomerController {

   @Autowired
   private PayClient payClient; //新增,用注入已经定义的接口方式

    @GetMapping("/customer")
    public String client(){
    
        String res = payClient.pay(); //调用一下即可
        return res;
    }
}

最后我们重启ClientCustomerApplication,此时5个服务应该都启动着
输入http://localhost:8080/customer

二、Feign含传递参数

1、单个参数用@PathVariable
2、多个参数用@RequestParam,不要省略value=""
3、传递对象,统一采用@RequestBody

第一步:导入依赖,启动Feign
eureka_client_customer的pom.xml新增依赖,并且consumer作为消费者(服务调用方,调用其他服务),需要在启动类开启Feign

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

eureka_client_pay的pom.xml也新增依赖

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

eureka_client_pay新增一个Order实体

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {

    private Integer id;

    private String name;

    private Integer price;

}

PayController新增一些服务,供用户调用,/pay/{id},/getOrder,/save三个接口,也就是与支付的订单有关的,怎么能让Customer模块能用到Pay模块的服务呢,之前用Eureka、Ribbon都可以做到,不过相比Feign还麻烦些

import com.yx.entity.Order;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

@RestController
public class PayController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/pay")
    public String pay(){
        String msg = "小明购买了一个充电宝,支付成功" + port;
        return msg;
    }

    @GetMapping("/pay/{id}")
    public Order findById(@PathVariable Integer id){
        return new Order(id, "充电宝", 66);
    }

    @GetMapping("/getOrder")
    public Order getOrder(@RequestParam Integer id, @RequestParam String name){
        return new Order(id, name, 66);
    }

    @PostMapping("/save")   //RequestBody不能用get,要用post
    public Order save(@RequestBody Order order){
        return order;
    }
}

第二步:定义接口
Feign只要在消费者(调用者)处定义接口,也就是customer中定义一个PayClient接口

注意接口用@FeignClient(“payClient”)修饰,payClient是要调用的服务名称,做一个映射,我们要使用支付服务所以,写支付的服务名称,application.yml配置了服务名称

import com.yx.entity.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

@FeignClient("payClient")   //写服务名称做一个映射
public interface PayClient {
    //Client接口中是不允许使用GetMapping的,只能是RequestMapping

    @RequestMapping(value = "/pay",method = RequestMethod.GET)
    String pay();   //支付服务的pay方法

    @RequestMapping(value = "/pay/{id}",method = RequestMethod.GET)
    Order findById(@PathVariable(value = "id") Integer id); //要写value

    @RequestMapping(value = "/getOrder",method = RequestMethod.GET)
    Order getOrder(@RequestParam(value = "id") Integer id, @RequestParam(value = "name") String name);//用RequestParam必须指定参数

    @RequestMapping(value = "/save",method = RequestMethod.POST)
    Order save(@RequestBody Order order);
}

你会发现里面的抽象方法都是按照PayController方法写的,没错,你可以理解成,PayController中的方法就是具体实现

定义完接口,就可以使用接口了,在CustomerController中使用,customer模块的端口是8080

import com.yx.client.PayClient;
import com.yx.entity.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CustomerController {

    @Autowired
    private PayClient payClient;

    @GetMapping("/customer")
    public String client(){

        String res = payClient.pay();
        return res;
    }

    @GetMapping("/customer/{id}")
    public Order findById(@PathVariable Integer id){
        return payClient.findById(id);
    }

    @GetMapping("/CustomerOrder")
    public Order getOrder(@RequestParam Integer id, @RequestParam String name){
        return payClient.getOrder(id,name);
    }

    @GetMapping("/save")
    public Order save(Order order){
        return payClient.save(order);
    }
}

我们可以在浏览器输入下面地址,得出结果

看看背后执行流程,以localhost:8080/customer/2为例,通过面向接口的形式,间接能获取到eureka_client_pay模块中PayController提供的服务

三、Feign的FallBack


FallBack可以帮助我们在使用Feign去调用另一个服务时,如果当前服务出现问题,可以走服务降级,返回一个错误数据,避免功能因为一个服务出现问题而全部失效,如何做?

第一步:创建一个POJO类,实现Client接口
在customer中controller文件夹同级创建一个fallback文件夹,并且在其中定义一个PayClientFallBack类实现CLient接口,如果对应类出现问题,就会返回这里信息

@Component
public class PayClientFallBack implements PayClient {
    @Override
    public String pay() {
        return "出现问题了!!!";
    }

    @Override
    public Order findById(Integer id) {
        return null;
    }

    @Override
    public Order getOrder(Integer id, String name) {
        return null;
    }

    @Override
    public Order save(Order order) {
        return null;
    }
}

第二步:修改Client接口中的注解,添加一个属性fallback

@FeignClient(value = "payClient", fallback = PayClientFallBack.class)

第三步:添加yml文件相关配置,这里就是启动

feign:
  hystrix:
    enabled: true

PayController写一个异常

然后启动customer和pay服务,浏览器输入http://localhost:8080/customer

确实会显示出现问题,但是控制台只是在payApplication显示异常信息,customerApplication调用者并没有显示异常信息,要想customer也显示异常,就要配置一个FallBackFactory

第一步:新建一个PayCLientFallBackFactory类,打印异常再返回fallback

@Component
public class PayClientFallBackFactory implements FallbackFactory<PayClient> {

    @Autowired
    private PayClientFallBack payClientFallBack;

    @Override
    public PayClient create(Throwable throwable) {
        throwable.printStackTrace();
        return payClientFallBack;
    }
}

第二步:修改注解属性,改成Factory

@FeignClient(value = "payClient", fallbackFactory = PayClientFallBackFactory.class) 

重启再刷新地址
于是customer和pay都会打印异常

代码压缩包:
链接:https://pan.baidu.com/s/1UI44KDXshnP4GU91nzyi9g
提取码:b5vy

以上是关于SpringCloud学习--- Feign详解(附代码压缩包)的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud---Feign上传下载详解

SpringCloud Feign使用详解

SpringCloud学习--- Hystrix详解(附代码包)

SpringCloud学习--- Hystrix详解(附代码包)

springcloud学习2:使用feign进行微服务之间的调用

springcloud学习2:使用feign进行微服务之间的调用