项目进行遇到一个问题,就是我们每增加一个服务调用的时候,基本都是增加一个Feign接口,这样可能会面临尴尬的问题,不同的URL调用时,会copy一堆的Feign接口,这显然不是我们最佳的方案,如果能使用一个Feign接口,在不同逻辑下动态请求不同的URL,同时不同的URL携带不同的Token信息…
TestFeignClient FeignClient接口:
@FeignClient(name = "TetsFeignClient")
public interface TestFeignClient {
@RequestLine("GET /test/healthcheck")
Object healthcheck(URI baseUri, @HeaderMap Map<String,Object> map);
@RequestLine("GET /test/{serverId}")
String getSomething2(URI baseUri, @Param("serverId") String serverId);
@RequestLine("POST /test/list")
Object list(URI baseUri,@HeaderMap Map<String,Object> map, QueryParam param);
application.yml配置如下:
api:
test:
homeUrl: http://xxx.test.com
TestCallerService 服务类,使用时直接注入这个Service即可
import xxx;
@Slf4j
@Component
@Import(FeignClientsConfiguration.class)
public class TestCallerService {
private TestFeignClient testFeignClient;
private URI uri;
//构造方法依赖yam文件中的参数,需要@Value注入对应的参数
public TestCallerService(Decoder decoder, Encoder encoder,@Value("${api.test.homeUrl}")String testHomeUrl) {
testFeignClient= Feign.builder()
.encoder(encoder)
.decoder(decoder)
.target(Target.EmptyTarget.create(TestFeignClient.class));
initUrl(testHomeUrl);
}
private void initUrl(String testHomeUrl){
try {
uri = new URI(testHomeUrl);
}catch (Exception e) {
log.info("初始化,{},{} TestClient error", testHomeUrl, e);
}
}
public Boolean healthcheck(String token){
try {
//我这里是接口测试使用的Object接收,自己根据实际情况转换成对应的DTO对象即可
Object result= testFeignClient.healthcheck(uri, handleRequestHeadInfo(token));
//...对应的接口调用逻辑处理
//...
}catch (Exception e){
//...对应的异常逻辑处理
}
}
/**
* 封装请求头部信息
* @param token
* @return
*/
private Map<String,Object> handleRequestHeadInfo(String token){
return ImmutableMap.of("Authorization",token,"Content-Type","application/json;charset=UTF-8");
}
上述实现总结:1、FeignClient 中不要写url, 使用 @RequestLine修饰方法
2、调用地方必须引入 FeignClientConfiguration, 必须有Decoder, Encoder
3、调用类必须以构建函数(Constructor) 的方式注入 FeignClient 类
4、传入URL作为参数;