集成Feign简化调用方式

open-feign
DerekYRC 3 years ago
parent c4cf557e30
commit d769f6d459

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

@ -475,16 +475,16 @@ spring:
Port of the service provider: 19922 Port of the service provider: 19922
``` ```
# [集成ribbon实现客户端负载均衡](#集成ribbon实现客户端负载均衡) # [集成ribbon实现客户端负载均衡](#集成ribbon实现客户端负载均衡)
> 代码分支: load-balancer > 代码分支: load-balancer
## 关于ribbon ## 关于ribbon
> (翻译自官方文档)ribbon是一个提供如下功能的依赖包:
> - 负载均衡 (翻译自官方文档)ribbon是一个提供如下功能的依赖包:
> - 容错机制 - 负载均衡
> - 支持多种协议(HTTP, TCP, UDP),支持异步和响应式的调用方式 - 容错机制
> - 缓存和批处理 - 支持多种协议(HTTP, TCP, UDP),支持异步和响应式的调用方式
- 缓存和批处理
#### ribbon核心API #### ribbon核心API
@ -971,6 +971,74 @@ public class ConsumerApplication {
访问```http://localhost:8080/foo``` 访问```http://localhost:8080/foo```
# [集成Feign简化调用方式](#集成Feign简化调用方式)
> 代码分支: open-feign
## 关于feign
[Open Feign](https://github.com/OpenFeign/feign) 是一个简化http调用方式的Java客户端通过处理接口的注解生成响应报文。使用示例:
```java
interface HelloService {
@RequestLine("GET /hello")
String hello();
}
@Test
public void testOpenFeign() {
HelloService helloService = Feign.builder()
.target(HelloService.class, "http://localhost:8080");
String response = helloService.hello();
}
```
Spring Cloud基于Open Feign开发了[Spring Cloud OpenFeign](https://github.com/spring-cloud/spring-cloud-openfeign) 得以支持Spring Mvc的注解通过实现feign的Contract接口实现类为SpringMvcContract使用示例:
```java
interface WorldService {
@GetMapping("/world")
String world();
}
@Test
public void testSpringCloudOpenFeign() {
WorldService worldService = Feign.builder()
.contract(new SpringMvcContract())
.target(WorldService.class, "http://localhost:8080");
String response = worldService.world();
}
```
可以dubug上面两个示例代码放在测试类FeignTest中重点关注Contract接口对注解的解析
#### Open Feign核心API
Open Feign工作流程:
![](./assets/feign工作流程.png)
一、Contract接口
负责解析Feign客户端接口的类注解、方法注解和参数。实现类```feign.Contract.Default```支持Open Feign的注解比如上面第一个示例中的RequestLine注解Spring Cloud OpenFeign开发的实现类```SpringMvcContract```支持Spring MVC的注解如GetMapping、PostMapping、RequestMapping。
二、Encoder接口
编码器,将请求对象编码为请求体
三、Decoder接口
解码器,将响应体解码为对象
四、RequestInterceptor拦截器接口
对请求进行拦截处理
五、Client接口
提交http请求的接口

@ -1,8 +1,5 @@
package com.github.cloud.openfeign.ribbon; package com.github.cloud.openfeign.ribbon;
import com.netflix.client.ClientException;
import com.netflix.client.ClientRequest;
import com.netflix.client.IResponse;
import feign.Client; import feign.Client;
import feign.Request; import feign.Request;
import feign.Response; import feign.Response;
@ -13,7 +10,6 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
/** /**
* feign client * feign client
@ -32,81 +28,23 @@ public class LoadBalancerFeignClient implements Client {
this.delegate = delegate; this.delegate = delegate;
} }
@SuppressWarnings("deprecation")
@Override @Override
public Response execute(Request request, Request.Options options) throws IOException { public Response execute(Request request, Request.Options options) throws IOException {
//客户端负载均衡 try {
URI original = URI.create(request.url()); //客户端负载均衡
String serviceId = original.getHost(); URI original = URI.create(request.url());
//选择服务实例 String serviceId = original.getHost();
ServiceInstance serviceInstance = loadBalancerClient.choose(serviceId); //选择服务实例
//重建请求URI ServiceInstance serviceInstance = loadBalancerClient.choose(serviceId);
URI uri = loadBalancerClient.reconstructURI(serviceInstance, original); //重建请求URI
URI uri = loadBalancerClient.reconstructURI(serviceInstance, original);
Response response = delegate.execute(new RibbonRequest(request, uri).toRequest(), options);
return new RibbonResponse(uri, response).getResponse(); Request newRequest = Request.create(request.httpMethod(), uri.toASCIIString(), new HashMap<>(),
}
private static class RibbonRequest extends ClientRequest {
private Request request;
public RibbonRequest(Request request, URI uri) {
this.request = request;
setUri(uri);
}
@SuppressWarnings("deprecation")
private Request toRequest() {
return Request.create(request.httpMethod(), getUri().toASCIIString(), new HashMap<>(),
request.body(), StandardCharsets.UTF_8); request.body(), StandardCharsets.UTF_8);
} return delegate.execute(newRequest, options);
} } catch (IOException e) {
throw new RuntimeException(e);
private static class RibbonResponse implements IResponse {
private final URI uri;
private final Response response;
protected RibbonResponse(URI uri, Response response) {
this.uri = uri;
this.response = response;
}
@Override
public Object getPayload() throws ClientException {
return response.body();
}
@Override
public boolean hasPayload() {
return response.body() != null;
}
@Override
public boolean isSuccess() {
return response.status() == 200;
}
@Override
public URI getRequestedURI() {
return uri;
}
@Override
public Map<String, ?> getHeaders() {
return new HashMap<>();
}
@Override
public void close() throws IOException {
if (response != null && response.body() != null) {
response.body().close();
}
}
public Response getResponse() {
return response;
} }
} }
} }

Loading…
Cancel
Save