美文网首页
Feign-Mock

Feign-Mock

作者: 张明学 | 来源:发表于2020-07-23 09:23 被阅读0次

    在项目开发中,会有调用第三方接口的场景。当开发或日常测试时,对方的服务挂了,我们就一直等着服务恢复,那么这就相当影响效率了。如果我们在开发时,就定义一个mock服务,在发起调用时,不直接调到第三方接口,而是调到我们自己的mock服务,这样就可以避免这些问题了。

    外部接口

    假如我们依赖外部一个的Fegin接口如下:

    @FeignClient(value = "sample-service-web", primary = false)
    public interface SampleServiceFeignApi {
        // 外部的接口
        @GetMapping("/info/{mid}")
        BaseResponse queryInfo(@PathVariable(value = "mid") Long mid);
    
    }
    
    mock实现

    定义一个实现类实现外部接口

    @Primary
    @Component
    @ConditionalOnProperty(name = "feign.mock.sample", havingValue = "true")
    public class SampleServiceFeignApiMock implements SampleServiceFeignApi{
        // 外部的接口的Mock实现
        @Override
        public BaseResponse queryInfo(Long mid) {
            return BaseResponse.result("Mock");
        }
    }
    
    配置说明
    • 外部接口(SampleServiceFeignApi)@FeignClient的primary要设置成false,mock实现类(SampleServiceFeignApiMock)需要加上@Primary

      解释:@FeignClient的primary默认为true,因为这个接口Fegin会代理实现类,这个类就是做为这个接口的实现类做依赖注入,我们自己又mock实现了一个,所以将我们自己的mock实现的要添加上@Primary,这样在满足@ConditionalOnProperty的条件情况下,优先依赖注入的是我们自己mock的类

    • mock实现类(SampleServiceFeignApiMock)需要加上@ConditionalOnProperty,并且配置加载参数的配置

    • 配置文件加上配置参数feign.mock.sample=true(Mock时配置,加载Mock类),feign.mock.sample=false(生产配置,不加载Mock类)

    配置了fallback的情况

    常用的fallback配置方式
    @FeignClient(value = "sample-service-web", fallback = SampleServiceFeignFallback.class, primary = false)
    public interface SampleServiceFeignApi {
        // 外部的接口
        @GetMapping("/info/{mid}")
        BaseResponse queryInfo(@PathVariable(value = "mid") Long mid);
    
    }
    
    @Component
    public class SampleServiceFeignFallback implements SampleServiceFeignApi {
        @Override
        public BaseResponse queryInfo(Long mid) {
            return BaseResponse.error("服务熔断");
        }
    }
    
    

    注意SampleServiceFeignFallback需要加@Component,被Spring去管理。正因如此,就不能使用以上方式实现mock,因为SampleServiceFeignApi设置了primary = false,在启用mock的时候SampleServiceFeignApiMock做为Primary,在不启用mock的时候,SampleServiceFeignFallback实现了SampleServiceFeignApi接口,加上Fegin自动生成的一个,SampleServiceFeignApi就有两个实现类并且都被Spring管理并且都没有设置Primary。

    fallbackFactory配置方式

    1、去掉SampleServiceFeignFallback的@Component,不让被Spring管理

    public class SampleServiceFeignFallback implements SampleServiceFeignApi {
        @Override
        public BaseResponse queryInfo(Long mid) {
            return BaseResponse.error("服务熔断");
        }
    }
    

    2、配置Fegin接口的fallbackFactory

    @FeignClient(value = "sample-service-web", fallbackFactory = SampleServiceFeignFallbackFactory.class, primary = false)
    public interface SampleServiceFeignApi {
        // 外部的接口
        @GetMapping("/info/{mid}")
        BaseResponse queryInfo(@PathVariable(value = "mid") Long mid);
    
    }
    

    3、开发FallbackFactory,可以输出Feign的错误原因。

    @Component
    @Slf4j
    public class SampleServiceFeignFallbackFactory implements FallbackFactory<SampleServiceFeignApi> {
    
        /**
         * fallback对象是否创建完毕
         */
        private AtomicBoolean fallbackObjectCreated = new AtomicBoolean(false);
        // 自己创建,不由Spring去管理SampleServiceFeignApi
        private SampleServiceFeignApi sampleServiceFeignApi = new SampleServiceFeignFallback();
    
        @Override
        public SampleServiceFeignApi create(Throwable throwable) {
            if (fallbackObjectCreated.get()) {
                // 打印fallback的原因, 方便定位问题
                log.warn(String.format("fallback due to: %s", throwable.getMessage()), throwable);
            } else {
                fallbackObjectCreated.compareAndSet(false, true);
            }
    
            return sampleServiceFeignApi;
        }
    }
    

    4、Mock的实现

    @Primary
    @Component
    @ConditionalOnProperty(name = "feign.mock.sample", havingValue = "true")
    public class SampleServiceFeignApiMock implements SampleServiceFeignApi{
        // 外部的接口的Mock实现
        @Override
        public BaseResponse queryInfo(Long mid) {
            return BaseResponse.result("Mock");
        }
    }
    

    配置说明:

    配置文件加上配置参数feign.mock.sample=true(Mock时配置,加载Mock类),feign.mock.sample=false(生产配置,不加载Mock类)

    相关文章

      网友评论

          本文标题:Feign-Mock

          本文链接:https://www.haomeiwen.com/subject/pwrclktx.html