Feign-Mock

2020-07-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");
    }
}
配置说明

配置了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类)

上一篇下一篇

猜你喜欢

热点阅读