Feign使用步骤详解及实操样例【Feign抽取、Feign继承】

Feign 是什么?

Feign 是 Netflix 公司开发的一个声明式的 REST 调用客户端;

Feign是声明式的 REST 调用客户端,那什么是声明式?

顾名思义,声明式就是只做声明,不作具体实现的方式。
即只需要告诉计算机,你想要得到什么样的结果,计算机则会给你想要的结果。

Feign使用步骤

1、引入Feign依赖

<!--feign客户端依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、Application启动类加入@EnableFeignClients注解

@MapperScan("cn.mapper")
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

3、编写FeignClient接口

接口口方法类似Controller,不同是无具体实现。

@FeignClient("userservice")
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

这个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:

服务名称:userservice
请求方式:GET
请求路径:/user/{id}
请求参数:Long id
返回值类型:User

这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。

4、调用生产者提供的服务时,将FeignClient接口注入,而后使用FeignClient接口

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.用Feign远程调用
        User user = userClient.findById(order.getUserId());
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }
}

Feign优点(与RestTemplate相比)

  1. 可读性更好(使用上类似与调用本地方法)
  2. 简化复杂URL(传入参数类似调用方法时的传参方式,更为简单直观)

Feign实操

方式一:抽取方式(推荐)

将Feign的Client抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。

例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包,即可直接使用。
Feign使用步骤详解及实操样例【Feign抽取、Feign继承】_第1张图片

1、 首先创建moudle,命名feign-api(可自定义),引入feign的starter依赖

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

2、创建userClient(feignClient),所需实体类及DefaultFeignConfiguration(默认配置)。

import feign.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "userservice")
public interface UserClient {

    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}
import lombok.Data;

@Data
public class User {
    private Long id;
    private String username;
    private String address;
}
import feign.Logger;
import org.springframework.context.annotation.Bean;

public class DefaultFeignConfiguration {
    @Bean
    public Logger.Level logLevel(){
        return Logger.Level.BASIC;
    }
}

3、在order-service中引入feign-api的依赖

<!--引入feign的统一api-->
<dependency>
    <groupId>cn.itcast.demo</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0</version>
</dependency>

4、使用feign-api进行调用

import cn.feign.clients.UserClient;
import cn.feign.pojo.User;
import cn.order.mapper.OrderMapper;
import cn.order.pojo.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.用Feign远程调用
        User user = userClient.findById(order.getUserId());
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }
}

5、解决feign-api中的类userClient不在order-service的SpringBootApplication的扫描包范围,致使FeignClient无法使用的问题。

两种解决方式:

1、使用注解@EnableFeignClients(basePackages = “cn.feign.clients”),指定userClient的所在包,包下所有类均被扫描
2、使用@EnableFeignClients(clients = UserClient.class),指定userClient的字节码,仅扫描指定类。
导入多个时,可以@EnableFeignClients(clients = {UserClient.class,orderClient.class})。(推荐该方式)

方式二:继承方式(不推荐)

优点: 面向契约编程,简单
缺点: 会造成服务端与消费者在API层面的紧耦合;且对SpringMVC不起作用,因为参数列表中的注解映射并不会继承(例如:@PathVariable),因此Controller中必须再次声明方法、参数列表、注解。

实现方式:

  1. 定义一个API接口,利用定义方法,并基于SpringMVC注解做声明
  2. Feign客户端和Controller都集成改接口
    Feign使用步骤详解及实操样例【Feign抽取、Feign继承】_第2张图片

你可能感兴趣的:(feign,分布式,java,spring,spring,boot)