Feign最佳实践

方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准

问题:

  • 服务紧耦合
  • 父接口参数列表中的映射不会被继承

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

实现步骤

创建一个module,命名为feign-api,引入feign的starter依赖

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

编写的UserClient、User、DefaultFeignConfiguration

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

 

@Data
public class User {
    private Long id;
    private String username;
    private String address;
}
View Code

 

public class FeignClientConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC;
    }
}
View Code

创建一个module,命名为use-feign-service

添加依賴

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

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

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>11.5</version>
        </dependency>

        <dependency>
            <groupId>com.marw</groupId>
            <artifactId>feign-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
View Code

创建启动类

@SpringBootApplication
@MapperScan("com.marw.usefeignservice.mapper")
@EnableFeignClients
public class UseFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(UseFeignApplication.class,args);
    }
}

添加配置信息(application.yaml)

server:
  port: 8088
spring:
  datasource:
    url: jdbc:mysql://192.168.223.129:3306/cloud-order?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  application:
    name: orderservice
  cloud:
    nacos:
      server-addr: localhost:80 # nacos 服务端地址
      discovery:
        cluster-name: HZ
#        namespace: b7b06ece-bd74-4a2d-b3a3-913942781562 #命名空间ID
        #ephemeral: false #是否是临时实例

mybatis:
  type-aliases-package: com.marw.feignclientservice.pojo
  configuration:
    map-underscore-to-camel-case: true
userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
feign:
  client:
    config:
      default:
        loggerLevel: Full
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

logging:
  level:
    com.marw: debug
View Code

创建Order、OrderMapper、OrderService(远程调用)、OrderController

    @Autowired
    private UserClient userClient;
    public Order queryById(Long id){
        Order order = orderMapper.findById(id);
        User user = userClient.findById(order.getUserId());
        order.setUser(user);
        return order;
    }

启动服务

Field userClient in com.marw.usefeignservice.service.OrderService required a bean of type 'com.marw.feign.client.UserClient' that could not be found.

错误原因:注入失败,在spring容器中无法找到

xxxxService服务启动时,spring会默认的扫描启动类(xxxApplication)所在包下的所有需要spring创建对象的注解,为其创建对象,

com.marw.feign.client.UserClient不在xxxxService的启动类所在的包下,所以spring就无法扫描和管理。

有两种方式解决:

在xxxxService服务的启动类(xxxApplication)的@EnableFeignClients注解中添加basePackages,指定FeignClient所在的包

@EnableFeignClients(basePackages = "xxxxx")

在xxxxService服务的启动类(xxxApplication)的@EnableFeignClients注解中添加clients,指定具体FeignClient的字节码

@EnableFeignClients(clients = {xxx.class})

 

posted @ 2021-10-18 15:03  一杯水M  阅读(764)  评论(0编辑  收藏  举报