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错误会报异常,提醒上层逻辑处理错误。

posted @ 2020-11-23 16:34  ralgo  阅读(233)  评论(0)    收藏  举报