给feign接口添加mock的一种简单方式
背景
项目使用feign来做微服务的调用,有时候会遇到一些问题:
- 剥离微服务时,A服务依赖的B服务未能及时提供响应
- 和不同的公司共同完成一个项目,各自提供一个微服务完成各自的业务,不同公司有自己各自的研发环境,但是又不能使用同一个服务注册中心
为了能够及时完成研发进度,不得不在约定好接口声明后,或者相互提供了feign-sdk后,给feign接口做代理来做接口mock。
下面是一种简单快速的mock方式。
关于LoadBalancerFeignClient
这个类是使用feign+ribbon来做负载均衡,找到对应的代理接口的类,关于其源码可以在csdn上找到很多资料,本次的实验方案是基于该类拓展来实现。
首先写一个自己的类继承这个类,重写execute方法:
public class MockLoadBalancerFeignClient extends LoadBalancerFeignClient {
@Override
public Response execute(Request request, Request.Options options) throws IOException {
//在这里做点什么吧
return super.execute(request, options);
}
}
具体重写的思路就是根据request的url路径去匹配一个需要mock的地址,如果找到需要mock的服务,那么就将url指向到mock服务器。
具体代码如下:
@Override
public Response execute(Request request, Request.Options options) throws IOException {
String url = request.url();
Optional<FeignMockServiceProperties.MockUrl> mockUrlOptional = mocks.getServices()
.stream()
.filter(m -> url.startsWith(m.getUrl()))
.findAny();
if (mockUrlOptional.isPresent()) {
// 重写请求地址,使用配置的mock地址去替代
FeignMockServiceProperties.MockUrl mockUrl = mockUrlOptional.get();
String newUrl = url.replaceFirst(mockUrl.getUrl(), mockUrl.getMock());
Request mockRequest = Request.create(request.httpMethod(), newUrl, request.headers(), request.body(), request.charset(), request.requestTemplate());
return getDelegate().execute(mockRequest, options);
}
return super.execute(request, options);
}
此处MockUrl
类是一个配置类,用于配置需要mock的url
前缀,和被代理的mock
地址,
@ConfigurationProperties(prefix = "feign.mock")
@Data
public class FeignMockServiceProperties {
private List<MockUrl> services;
@Data
static class MockUrl {
/**
* 需要代理的url地址
**/
private String url;
/**
* mock指向的url地址
**/
private String mock;
}
}
然后我们将MockLoadBalancerFeignClient
声明为一个bean
此处使用到了OkHttpClient
,根据需要也可以选择其他的方式
@Bean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) {
// 使用OkHttpClient,也可以用其他的
OkHttpClient delegate = new OkHttpClient(okHttpClient);
return new MockLoadBalancerFeignClient(delegate, cachingFactory, clientFactory, mockServiceProperties);
}
FeignMockServiceProperties指向yml文件中的配置,例如
feign:
# 启用okhttp
okhttp:
enabled: true
# 使用mock服务
mock:
services:
- url: http://service-a
mock: http://mock-service-a
这是一种比较简单的方式,另外还有一种比较重量级的玩法,重写feign代理生成的过程,当发现需要代理的服务时,直接替换其代理类,下次再说~