Spring Cloud服务调用
OpenFeign核心apiSpring Cloud Feign使用RestTemplate自定义实现服务调用Spring Cloud Feign源码分析
Spring Cloud服务调用
版本信息
Spring Cloud : Hoxton.SR1
Spring Boot : 2.2.2.RELEASE
Zookeeper : 3.5.6 (注册中心使用)
OpenFeign核心api
Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket
feign.Feign核心类feign.Contract服务接口类的注解和值解析feign.Client调用feign.Retryer重试feign.codec.Encoder序列化,对象转成Http请求feign.codec.Decoder反序列化,Http请求转换为对象feign.QueryMapEncoder查询参数的编码feign.codec.ErrorDecoder错误信息编码feign.Request请求参数feign.InvocationHandlerFactory控制反射方法分派
Spring Cloud Feign使用
服务端
一个简单的对外提供服务,基于
Zookeeper注册中心
添加
pom依赖1
2
3
4
5
6
7
8
9
10
11
12
13
14<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--zookeeper 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>简单的对外提供服务端点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/**
* 演示服务端点
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/7
*/
@RestController
public class EchoController {
@Autowired
private Environment environment;
@GetMapping("/echo")
public String echo(@RequestParam String message) {
// 由于采用的是随机端口,这地方必须采用这个方式获取端口
String port = environment.getProperty("local.server.port");
return "ECHO(" + port + "):" + message;
}
}配置文件
application.yml1
2
3
4
5
6
7
8spring:
application:
name: feign-server
cloud:
zookeeper:
connect-string: 127.0.0.1:2181
server:
port: 0服务启动程序类
FeignServerApplication1
2
3
4
5
6
7
8
9
10
11
12
13/**
* Feign 服务端应用
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/7
*/
@SpringBootApplication
public class FeignServerApplication {
public static void main(String[] args) {
SpringApplication.run(FeignServerApplication.class, args);
}
}启动服务,根据启动日志查看本地的随机端口,此次端口是
60981http://127.0.0.1:60981/echo?message=Hello返回信息ECHO(60981):Hello
客户端
添加
pom依赖1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--zookeeper 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
<!--openfeign 客户端调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>服务提供接口
1
2
3
4
5
6
7
8
9
10
11
12/**
* 服务提供echo服务
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/7
*/
@FeignClient("feign-server") //标注是Feign Client
public interface EchoService {
@GetMapping("/echo")
String echo(@RequestParam("message") String message);
}客户端提供服务端点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/**
* 演示服务端点
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/7
*/
@RestController
public class EchoController {
@Autowired
private EchoService echoService;
@GetMapping("/echo")
public String echo(String message) {
return this.echoService.echo(message);
}
}配置文件
application.yml1
2
3
4
5
6
7
8spring:
application:
name: feign-client
cloud:
zookeeper:
connect-string: 127.0.0.1:2181
server:
port: 8090服务启动程序类
FeignClientApplication1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* Feign 客户端服务
*
* @author FelixFly <chenglinxu@yeah.net>
* @date 2020/2/7
*/
@SpringBootApplication
@EnableFeignClients(clients = EchoService.class) //启用Feign Client
public class FeignClientApplication {
public static void main(String[] args) {
SpringApplication.run(FeignClientApplication.class, args);
}
}启动服务,
http://localhost:8090/echo?message=hello返回信息ECHO(60981):hello
RestTemplate自定义实现服务调用
自定义客户端调用注解
1 | |
自定义客户端调用服务
1 | |
自定义客户端启用注解
1 | |
导入RestFeignClientsRegistrar
1 | |
动态代理调用RestFeignClientInvocationHandler
1 | |
启动添加启用注解
1 | |
演示服务端点
1 | |
启动服务,
http://localhost:8090/rest/echo?message=hello返回信息ECHO(60981):hello
Spring Cloud Feign源码分析
@EnableFeignClients分析
1 | |
导入了FeignClientsRegistrar
1 | |
注册了FeignClientFactoryBean
1 | |
构建了一个Feign调用,客户端有两种LoadBalancerFeignClient以及FeignBlockingLoadBalancerClient,
配置属性FeignClientProperties
OpenFeign核心api在Spring Cloud中的扩展
org.springframework.cloud.openfeign.FeignClientsConfiguration默认的配置类
feign.Contract服务接口类的注解和值解析org.springframework.cloud.openfeign.support.SpringMvcContract支持
Spring MVC的注解,比如@RequestMapping、@PathVariable等等参数注解处理核心接口:
org.springframework.cloud.openfeign.AnnotatedParameterProcessorr@PathVariablePathVariableParameterProcessor@RequestParamRequestParamParameterProcessor@RequestHeaderRequestHeaderParameterProcessor@SpringQueryMapQueryMapParameterProcessor
feign.Client调用org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClientRibbon客户端调用org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient阻塞的Feign客户端,Spring Cloud LoadBalanced实现
feign.Retryer重试Retryer.NEVER_RETRY不进行重试
feign.codec.Encoder序列化,对象转成Http请求new SpringEncoder(this.messageConverters)普通的反序列化new PageableSpringEncoder(new SpringEncoder(this.messageConverters))带有分页参数的反序列化
从上可以得知,这个序列是通过
HttpMessageConverter组合去处理的feign.codec.Decoder反序列化,Http请求转换为对象new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)))
从上可以得知,这个反序列是通过
HttpMessageConverter组合去处理的