OpenFeign的使用

写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!如果我的博客对你有帮助,欢迎进行评论✏️✏️、点赞👍👍、收藏⭐️⭐️,满足一下我的虚荣心💖🙏🙏🙏 。

目录

使用

测试准备

依赖包

EnableFeignClients注解

@FeignClient

定义fallback

定义fallbackFactory

测试

超时时间配置


使用

测试准备

在商品服务中声明一个测试方法,其它代码省略:

@RequestMapping("/test")
@RestController
public class TestController {
    
    @Autowired
    private GoodsMapper mapper;

    @RequestMapping
    public ResponseEntity<List<GoodsDto>> getGoods(QueryPage page){
        IPage<GoodsDto> resultPage = mapper.selectPage(page, new QueryWrapper<>());
        return ResponseEntity.ok().headers(PageHeader.getPageHeader(resultPage))
                .body(resultPage.getRecords());
    }
}
依赖包
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>@
EnableFeignClients注解

在启动类或者配置类上加@EnableFeignClients注解:

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
public class DemoApplication {

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

}

如上,我们这个服务只是为了测试用,不需要连接数据库,但是如果不配置数据库连接启动会报错,需要加上exclude排除默认加载的数据库配置类。

@FeignClient

使用@FeignClient注解声明Feign接口:

@FeignClient(name = "goods-service", fallback = GoodsFallbackService.class,contextId = "testFeignClient")
public interface TestFeignClient {
    @GetMapping("/test")
    ResponseEntity<List<GoodsDto>> list(QueryPage page);
}

如上,声明了一个查询商品列表的接口,下面对使用到的几个参数进行简单说明:

goods-service:商品服务注册到nocos的服务名,即spring.application.name配置的名字。

fallback:调用方法异常时执行。

contextId:定义bean的名称。

定义fallback

在fallback中实现服务降级的逻辑,这里只是打印了下日志返回一个状态码:

@Component
@Slf4j
public class GoodsFallbackService implements TestFeignClient {

    @Override
    public ResponseEntity<List<GoodsDto>> list(QueryPage page) {
        log.debug("调用商品服务失败");
        return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build();
    }
}
定义fallbackFactory

除了使用fallback定义降级,还可以使用@FeignClient中的fallbackFactory进行回调,使用@FeignClient中的fallbackFactory需要自己去实现FallbackFactory接口,泛型使用对应的TestFeignClient,我们实现FallbackFactory接口的create方法可以看到入参是一个Throwable,我们可以对异常类型和异常信息进行对应的处理。注意,要实现的是feign.hystrix.FallbackFactory而不是org.springframework.cloud.openfeign.FallbackFactor,如下:

@FeignClient(value = "goods-service", fallbackFactory = GoodsFallbackFactory.class,contextId = "testFeignClient",configuration = FeignConfig.class)
public interface TestFeignClient {

    @GetMapping("/test")
    ResponseEntity<List<GoodsDto>> list(QueryPage page);

}
@Component
@Slf4j
public class GoodsFallbackFactory implements FallbackFactory<TestFeignClient> {
    @Override
    public TestFeignClient create(Throwable cause) {
        TestFeignClient testFeignClient = new TestFeignClient() {
            @Override
            public ResponseEntity<List<GoodsDto>> list(QueryPage page) {
                log.debug("调用商品服务失败");
                cause.printStackTrace();
                return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build();
            }
        };
        return testFeignClient;
    }
}
测试

demo服务中添加测试方法:

@GetMapping
@ResponseBody
public ResponseEntity<List<GoodsDto>> testFeign() {
   ResponseEntity<List<GoodsDto>> responseEntity = client.list(new QueryPage());
   System.out.println(responseEntity.getHeaders().get(PageConst.PAGINATION_COUNT_HEADER));
   return responseEntity;
}

浏览器访问 结果如下:

如上,说明使用openfeign调用商品服务成功。

超时时间配置

ERROR SocketTimeoutException: Read timed out (6768ms)

在调用远程服务时避免因为服务异常迟迟不能返回数据对后续操作造成影响,需要配置openfeign的超时时间结合前面配置的fallback实现服务降级处理,超时时间的配置分如下几种:

默认给openfeign设置超时时间,全局生效,如下:

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000

如果想对某一个服务生效,如下:

feign:
  client:
    config:
      goods-service:
        connectTimeout: 10000
        readTimeout: 60000

如上,配置的超时时间只对goods-service生效,goods-service为@FeignClient中的value/name。

如果还想更精细化的区分也可以通过contxtId进行区分,如下:

@FeignClient(value = "goods-service", fallback = GoodsFallbackService.class,contextId = "testFeignClient",configuration = FeignConfig.class)
public interface TestFeignClient {
    @GetMapping("/test")
    ResponseEntity<List<GoodsDto>> list(QueryPage page);
}
feign:
  client:
    config:
      testFeignClient:
        connectTimeout: 10000
        readTimeout: 60000

还可以使用编码的方式配置,本着 约定 > 配置 > 编码 的原则,这里就使用配置方式进行设置。

补充说明下contextId:

比如我们有多个@FeignClient设置的value(name) 服务名称为user 并且没有设置contextId ,那么在注册Bean 信息的时候BeanName 就会重复,Spring 原生是支持覆盖的,也就是说如果BeanName 相同那么后注册的就会将先注册的替换,但是在SpringBoot 中会将这个覆盖配置关闭,如果出现一样的BeanName 那么就会抛出下面那个异常信息,解决方法常用有两种开启第一种SpringBoot 覆盖配置、第二种在@FeignClient中设置contextId ,推荐使用第二种,这就是contextId的作用之一。

Description:
The bean ‘kerwin-user.FeignClientSpecification’ could not be registered. A bean with that name has already been defined and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值