Spring Cloud(一)Feign
Feign的Http库
Feign是一个声明式的http客户端,它定义了一些接口来帮助用户更加方便地开发Http服务。Feign并没有重新开发底层http库,而是重用了一些车轮,比如它默认是使用java.net.HttpURLConnection,除了默认的http库外它还支持:Apache的HttpClient、google的HttpClient、java11的HTTP2、okhttp等等。
Feign和线程
每个Feign客户端实例都应该在单独一条线程中运行,和其他客户端实例隔离开,这是因为它的重试组件Retryer会在重试时阻塞线程(Thread.sleep)。
Feign是如何整合Ribbon的?
Feign为了整合Ribbon,提供一个类叫RibbonClient,这个类介于Feign和http库之间,代码如下:
public class Example {
public static void main(String[] args) {
MyService api = Feign.builder()
.client(RibbonClient.create())
.target(MyService.class, "https://myAppProd");
}
}
在默认情况且没有RibbonClient这一层的情况下,请求直接通过java.net.HttpURLConnection到达目标,但是如果加了RibbonClient这一层,请求会先经过Ribbon的处理,然后再通过java.net.HttpURLConnection到达目标。
模板和表达式
如果你用过JSP,就知道一个模板就是包含了一些占位符的jsp文件,Feign的模板和JSP的模板有点相似,Feign的表达式和JSP的占位符相似。
Feign的表达式来自由URI模板RFC 6570所定义的Simple String Expressions (Level 1)。表达式展开时会使用对应的由Param注解标注的方法参数。下面是一个例子:
interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
}
public static class Contributor {
String login;
int contributions;
}
public class MyApp {
public static void main(String... args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
// Fetch and print a list of the contributors to this library.
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
表达式必须是位于花括号{}中,可能包含正则表达式来约束值的范围,表达式的名称和正则表达式由冒号 : 分开。比如这个例子,owner必须是字母。{owner:[a-zA-Z]*}。
编程的方式使用模板
参考Feign-Core的单元测试,那里有关于Body、Header、Query、Uri模板的使用,下面是一个简单的例子:
public class UriTemplateExample {
public static void main(String args[]) {
String template = "https://www.example.com/{foo:[0-9]*}/{bar}/details";
UriTemplate uriTemplate = UriTemplate.create(template, Util.UTF_8);
Map<String, Object> variables = new LinkedHashMap<>();
variables.put("foo", "123");
variables.put("bar", "second");
String expandedTemplate = uriTemplate.expand(variables);
System.out.println(expandedTemplate);
}
}
public class QueryTemplateExample {
public static void main(String args[]) {
QueryTemplate template = QueryTemplate.create("people", Collections.singletonList("{people}"), Util.UTF_8);
String expanded = template.expand(Collections.singletonMap("people", Arrays.asList("Bob", "James", "Jason")));
System.out.println(expanded);
}
}
注意要在pom.xml添加依赖:
<!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-core -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>10.11</version>
</dependency>
feign与4xx、5xx错误
feign接收到4xx、5xx错误会报异常,提醒上层逻辑处理错误。

浙公网安备 33010602011771号