https://github.com/OpenFeign/feign
Feign使得 Java HTTP 客户端编写更方便。
Feign最初是为了降低统一绑定Denominator到HTTP API的复杂度,不区分是否支持Restful。
Feign旨在通过最少的资源和代码来实现和HTTP API的连接。
通过可定制的解码器和错误处理,可以编写任意的HTTP API。
Feign可以结合hystrix一起使用,hystrix通过服务隔离、熔断(也可以称为断路)、降级等手段控制依赖服务的延迟与失败。
主要特点:
- 定制化
- 提供多个接口
- 支持JSON格式的编码和解码
- 支持XML格式的编码和解码
代码示例:
import feign.*;
import feign.codec.ErrorDecoder;
import feign.codec.Decoder;
import feign.gson.GsonDecoder;
import java.io.IOException;
import java.util.List;
public class GitHubExample {
interface GitHub { // 1
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
}
public static void main(String... args) {
Decoder decoder = new GsonDecoder(); // 2
GitHub github = Feign.builder()
.decoder(decoder) // 3
.errorDecoder(new GitHubErrorDecoder(decoder)) // 4
.logger(new Logger.ErrorLogger()) // 5
.logLevel(Logger.Level.BASIC) // 5
.target(GitHub.class, "https://api.github.com"); // 6
System.out.println("Let's fetch and print a list of the contributors to this library.");
List<Contributor> contributors = github.contributors("netflix", "feign"); // 7
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
System.out.println("Now, let's cause an error.");
try {
github.contributors("netflix", "some-unknown-project"); // 8
} catch (GitHubClientError e) {
System.out.println(e.getMessage());
}
}
static class Contributor {
String login;
int contributions;
}
static class GitHubClientError extends RuntimeException { // 4
private String message; // parsed from json
@Override
public String getMessage() {
return message;
}
}
static class GitHubErrorDecoder implements ErrorDecoder { // 4
final Decoder decoder;
final ErrorDecoder defaultDecoder = new ErrorDecoder.Default();
GitHubErrorDecoder(Decoder decoder) {
this.decoder = decoder;
}
@Override
public Exception decode(String methodKey, Response response) {
try {
return (Exception) decoder.decode(response, GitHubClientError.class);
} catch (IOException fallbackToDefault) {
return defaultDecoder.decode(methodKey, response);
}
}
}
}
1. 首先定义接口GitHub,使用注解RequestLine 表明contributors()方法为一个get请求,请求相对为/repos/{owner}/{repo}/contributors;
2. Decoder decoder = new GsonDecoder(); 创建一个GsonDecoder解码器,表明通过Gson解析返回数据;
3. decoder()方法设置解码器 ;
4. errorDecoder()指定发生异常时的解码器,需要实现ErrorDecoder接口,覆写decode方法,通过指定的Decoder解析错误信息,这里还是使用GsonDecoder ;
5. logger()方法配置日志;
6. target() 方法指定访问url以及返回的类型;
7. 通过创建的github对象调用contributors获取结果;
8. 模拟异常情况。
可定制:
Feign在一些方面可以定制。举个简单的例子,可以使用Feign.builder()来构建一个API 接口,包含自定义的内容。
interface Bank {
@RequestLine("POST /account/{id}")
Account getAccountInfo(@Param("id") String id);
}
...
Bank bank = Feign.builder()
.decoder(new AccountDecoder())
.target(Bank.class, "https://api.examplebank.com");
支持多种接口:
Feign可以提供多种API 接口。这些都被定义为Target<T>(默认为 HardCodeTarget<T>)。它允许动态扩展,并且被修饰过的请求会被优先执行。
例如,以下部分可以修饰来自当前身份验证服务的URL和AUTH的每一个请求。
Feign feign = Feign.builder().build();
CloudDNS cloudDNS = feign.target(new CloudIdentityTarget<CloudDNS>(user, apiKey));