# spring cloud feign
introduction
netflix feign
是一个类似retrofit
进行http调用框架,Feign makes writing Java http clients easier
使得编写http client
代码更加简单
netflix feign
直接给出一段简单的案例
package com.lkl.netflix.feign;
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 {
@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();
GitHub github = Feign.builder()
.decoder(decoder)
.errorDecoder(new GitHubErrorDecoder(decoder))
.logger(new Logger.ErrorLogger())
.logLevel(Logger.Level.BASIC)
.target(GitHub.class, "https://api.github.com");
System.out.println("Let's fetch and print a list of the contributors to this library.");
List<Contributor> contributors = github.contributors("netflix", "feign");
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");
} catch (GitHubClientError e) {
System.out.println(e.getMessage());
}
}
static class Contributor {
String login;
int contributions;
}
static class GitHubClientError extends RuntimeException {
private String message;
@Override
public String getMessage() {
return message;
}
}
static class GitHubErrorDecoder implements ErrorDecoder {
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
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
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.模拟异常情况
note: feign
使用起来很简单,其原理和retrofit
及其类似,通过接口定义访问访问,用jdk的动态代理创建接口的实现类,在类中解析方法上的注解信息用以识别用户配置的http请求信息,然后执行请求;
feign可以通过ReflectiveFeign
下的newInstance()
方法看到
return (T) Proxy
.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);
spring cloud feign
spring cloud feign
通过注解的封装使用起来更加简单
package com.lkl.springcloud.feign
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.cloud.netflix.feign.EnableFeignClients
import org.springframework.cloud.netflix.feign.FeignClient
import org.springframework.context.annotation.Configuration
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RestController
import java.util.List
@Configuration
@EnableAutoConfiguration
@EnableFeignClients
@RestController
public class Application {
@Autowired
GitHub gitHub
public static void main(String[] args) {
SpringApplication.run(Application.class, args)
}
@FeignClient(url = "https://api.github.com")
interface GitHub {
@RequestMapping(value = "/repos/{owner}/{repo}/contributors", method = RequestMethod.GET)
ResponseEntity<List<Contributor>> contributors(@PathVariable("owner") String owner, @PathVariable("repo") String repo)
}
@RequestMapping("/")
public void test(){
ResponseEntity< List<Contributor>> responseEntity = gitHub.contributors("netflix", "feign")
List<Contributor> contributors = responseEntity.getBody()
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")")
}
}
static class Contributor {
String login
int contributions
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
注解EnableFeignClients
表明需要扫描使用FeignClient
注解的接口,在代码中定义了@FeignClient(url = "https://api.github.com")
表明该接口为一个feign接口
通过url
指定访问路径RequestMapping
表明相对路径
在代码中注入beanGitHub
,直接调用其中申明的方法即可。
重点说明下FeignClient
注解
该注解表示申明创建一个rest client bean,可以直接通过Autowired
注入使用,如果ribbon在工程中启用,则会使用load balance
进行后端请求调用,可以为FeignClient
指定value表明需要访问的serviceId
feign + ribbon + eureka
在springcloud(第七篇)springcloud ribbon with eureka中讲解了ribbon+eureka,其中使用RestTemplate
进行调用,也可以通过
feign
调用
package com.lkl.springcloud.feign
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.cloud.client.discovery.EnableDiscoveryClient
import org.springframework.cloud.netflix.feign.EnableFeignClients
import org.springframework.cloud.netflix.feign.FeignClient
import org.springframework.cloud.netflix.ribbon.RibbonClient
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import static org.springframework.web.bind.annotation.RequestMethod.GET
@SpringBootApplication
@EnableDiscoveryClient
@RestController
@RibbonClient("hello")
@EnableFeignClients
public class Application {
@Autowired
HelloClient client
@RequestMapping("/")
public String hello() {
return client.hello()
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args)
}
@FeignClient("simple")
interface HelloClient {
@RequestMapping(value = "/", method = GET)
String hello()
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
使用@FeignClient("simple")
指定要访问的service id
由于hello()
对应的mapping为@RequestMapping(value = "/", method = GET)
那么该方法实际调用url为
http://simple/
,因此在执行
@RequestMapping("/")
public String hello() {
return client.hello();
}
调用的为SimpleApplication.java
中
@RequestMapping("/")
public String hello() {
return "Hello";
}
ok ~ it’s work ! more about is here