Spring Cloud 声明式服务调用 Feign
来源:互联网 发布:数据库开发 编辑:程序博客网 时间:2024/05/21 10:16
一、简介
在上一篇中,我们介绍注册中心Eureka,但是没有服务注册和服务调用,服务注册和服务调用本来应该在上一章就应该给出例子的,但是我觉得还是和Feign一起讲比较好,因为在实际项目中,都是使用声明式调用服务。而不会在客服端和服务端存储2份相同的model和api定义。Feign在RestTemplate的基础上对其封装,由它来帮助我们定义和实现依赖服务接口的定义。Spring Cloud Feign 基于Netflix Feign 实现的,整理Spring Cloud Ribbon 与 Spring Cloud Hystrix,并且实现了声明式的Web服务客户端定义方式。
二、实践
在上一节中,我继续添加工程模块,最后的模块如下:
首先我们需要建一个工程,名为hello-service-api 在工程主要定义对外提供的model 和api。服务的提供方和服务的消费方都要依赖该工程jar,这样我们就可以只维护一份model 和api定义。在该例子中主要如下结构
非常简单,只有1个HelloServieRemoteApi 接口定义和User对象。
@RequestMapping
(
"/hello-service-remote"
)
public
interface
HelloServiceRemoteApi {
@RequestMapping
(value =
"/hello1"
, method = RequestMethod.GET)
String hello(
@RequestParam
(
"name"
) String name);
@RequestMapping
(value =
"/hello2"
, method = RequestMethod.GET)
User hello(
@RequestHeader
(
"name"
) String name,
@RequestHeader
(
"age"
) Integer age);
@RequestMapping
(value =
"/hello3"
, method = RequestMethod.POST)
String hello(
@RequestBody
User user);
}
在上面的接口定义中,我们非常的清晰,在接口上面我们主映射为/hello-service-remote,个人感觉已接口的名字通过“-”这样可以非常的区分不同的接口路径,防止多接口时发生重复。接下来具体方法的上面可以定义于方法名一样的路径映射,我这里已 /hello1,/hello2,/hello3为主。
public
class
User
implements
Serializable {
private
static
final
long
serialVersionUID = -7233238826463139634L;
private
Long id;
private
String name;
private
Integer age;
public
User() {
}
public
User(String name, Integer age) {
this
.name = name;
this
.age = age;
}
public
Long getId() {
return
id;
}
public
void
setId(Long id) {
this
.id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
Integer getAge() {
return
age;
}
public
void
setAge(Integer age) {
this
.age = age;
}
@Override
public
String toString() {
return
"User{"
+
"name='"
+ name + '\
''
+
", age="
+ age +
'}'
;
}
}
上面就是简单的一个User对象。
从上面的接口中发现,该api工程需要引入spring-web包。所以它的pom.xml如下:
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<project xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0
.
0
</modelVersion>
<artifactId>hello-service-api</artifactId>
<version>
1.0
-SNAPSHOT</version>
<groupId>com.qee.hello</groupId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>
4.2
.
9
.RELEASE</version>
</dependency>
</dependencies>
</project>
从上面的pom.xml定义中,我们知道hello-service-api并不集成父工程micro-service-integration。一般作为api提供的工程jar,依赖越少越好。
接下来我们需要创建一个提供者工程,我们把它命名为hello-service-compose。该工程也是标准的Spring Boot工程。具体的目录如下:
在工程中我们有一个刚才hello-service-api接口定义的实现。代码如下:
@RestController
public
class
HelloServiceRemoteApiImpl
implements
HelloServiceRemoteApi {
@Override
public
String hello(
@RequestParam
(
"name"
) String name) {
return
"hello "
+ name;
}
@Override
public
User hello(
@RequestHeader
(
"name"
) String name,
@RequestHeader
(
"age"
) Integer age) {
try
{
name= URLDecoder.decode(name,
"UTF-8"
);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
new
User(name, age);
}
@Override
public
String hello(
@RequestBody
User user) {
if
(user ==
null
) {
return
"未知"
;
}
return
user.toString();
}
}
因为是测试工程,所以它没有复杂的业务逻辑。接下来就是HelloProviderApplication的启动main.
package
com.qee.remote;
import
org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public
class
HelloProviderApplication {
public
static
void
main(String[] args) {
SpringApplication.run(HelloProviderApplication.
class
, args);
}
}
在上面有2个注解,第一个 SpringBootApplication 就是Spring Boot 启动注解,EnableDiscoveryClient 该注解会把RestController修饰的类注册到注册中心去。
接下来我们来看下application.properties
server.port=
8885
spring.application.name=hello-service-compose
eureka.instance.hostname=register.center.com
eureka.instance.server.port=
8881
#默认的注册域
eureka.client.serviceUrl.defaultZone=http:
//${eureka.instance.hostname}:${eureka.instance.server.port}/eureka/
#控制台彩色输出
spring.output.ansi.enabled=ALWAYS
从上面信息我们知道,改工程启动端口为8885,注册中心地址为register.center.com:8881。
接下来我们查看一下该工程的pom.xml定义
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<project xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<parent>
<artifactId>micro-service-integration</artifactId>
<groupId>spring.cloud</groupId>
<version>
1.0
-SNAPSHOT</version>
</parent>
<modelVersion>
4.0
.
0
</modelVersion>
<artifactId>hello-service-compose</artifactId>
<properties>
<project.build.sourceEncoding>UTF-
8
</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-
8
</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.qee.hello</groupId>
<artifactId>hello-service-api</artifactId>
<version>
1.0
-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
从pom.xml文件中知道该工程依赖了web,euraka,ribbon,actuator,hello-service-api 包。其中euraka为服务注册和发现包,ribbon为服务调用负载均衡包,actuator为工程元信息检测包。还有我们自己定义的hello-service-api包。
在上面的简单配置和编写后,我们就可以启动工程把该HelloServiceRemoteApi注册到注册中心去了。
现在有了服务接口定义包和服务提供工程,现在我们编写一下服务调用工程。命名为hello-service-web。该工程的目录结构如下:
首先我们来看下HelloBackgroundService 这个接口。
@FeignClient
(value =
"hello-service-compose"
)
public
interface
HelloBackgroundService
extends
HelloServiceRemoteApi{
}
非常的简单,主要继承我们之前编辑的HelloServiceRemoteApi,并且在上面打上FeignClient注解,该注解指定服务名来绑定服务。该注解同时会使服务调用具有负载均衡的能力。
接下来我们来看下HelloController类
@RestController
public
class
HelloController {
@Autowired
private
HelloBackgroundService helloBackgroundService;
@RequestMapping
(
"/hello"
)
public
Map<String,Object> hello(){
Map<String,Object> ret =
new
HashMap<String, Object>();
StringBuffer sb =
new
StringBuffer();
String s1 = helloBackgroundService.hello(
"张三"
);
sb.append(s1).append(
"\n"
);
User user =
null
;
try
{
user = helloBackgroundService.hello(URLEncoder.encode(
"李四"
,
"UTF-8"
),
30
);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
sb.append(user.toString()).append(
"\n"
);
String s3 = helloBackgroundService.hello(
new
User(
"王五"
,
19
));
sb.append(s3).append(
"\n"
);
ret.put(
"show"
,sb.toString());
return
ret;
}
}
从上面得知我们,我们就可以调用之前的我们编写的HelloBackgroundService了。接下来我们查看一下启动类HelloConsumerApp
package
com.qee;
import
feign.Logger;
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.context.annotation.Bean;
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public
class
HelloConsumerApp {
@Bean
Logger.Level feginLoggerLevel(){
return
Logger.Level.FULL;
}
public
static
void
main(String[] args) {
SpringApplication.run(HelloConsumerApp.
class
, args);
}
}
在该启动了中又多了一个注解EnableFeignClients ,该注解开启Spring Cloud Feign的支持。接着我们来查看一下application.properties
server.port=
8887
spring.application.name=hello-service-web
eureka.instance.hostname=register.center.com
eureka.instance.server.port=
8881
#默认的注册域
eureka.client.serviceUrl.defaultZone=http:
//${eureka.instance.hostname}:${eureka.instance.server.port}/eureka/
#开启请求压缩功能
feign.compression.request.enabled=
true
#开启响应压缩功能
feign.compression.response.enabled=
true
#指定压缩请求数据类型
feign.compression.request.mime-types=text/xml;application/xml;application/json
#如果传输超过该字节,就对其进行压缩
feign.compression.request.min-request-size=
2048
#控制台彩色输出
spring.output.ansi.enabled=ALWAYS
#日志配置,该接口的日志级别
logging.level.com.qee.service.HelloBackgroundService=DEBUG
从上面的注释中,我们已经可以知道具体的配置参数的作用,这里就不详细介绍了。从上面的配置和编写我们可以知道,该工程需要如下的依赖包,pom.xml文件如下
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<project xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<parent>
<artifactId>micro-service-integration</artifactId>
<groupId>spring.cloud</groupId>
<version>
1.0
-SNAPSHOT</version>
</parent>
<modelVersion>
4.0
.
0
</modelVersion>
<artifactId>hello-service-web</artifactId>
<properties>
<project.build.sourceEncoding>UTF-
8
</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-
8
</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.qee.hello</groupId>
<artifactId>hello-service-api</artifactId>
<version>
1.0
-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
该服务消费端,比服务提供方多了一个jar依赖,就是feign。该jar的作用就是提供声明式的服务调用。到这里我们本章的内容大致结束,最后我们来运行这几个工程。查看如下结果:
从上面我们可以看到2个工程hello-service-compose 和hello-service-web都已经注册到注册中心eureka上了。接下来看一下调用结果:
到这里服务注册中心启动,服务注册,服务消费大致都已完成,之后会向大家一起学习服务调用的负载均衡Ribbon和服务容错保护Hystrix.
- Spring Cloud 声明式服务调用 Feign
- 声明式服务调用:Spring Cloud Feign
- spring cloud Feign(声明式服务调用)
- Spring Cloud入门教程(三):声明式服务调用(Feign)
- Spring Cloud中声明式服务调用Feign
- 06.Spring Cloud学习笔记之声明式服务调用组件Feign
- Spring Cloud学习--声明式调用(Feign)
- spring cloud feign 调用服务注意问题
- Spring Cloud学习系列第二章:使用Feign调用服务
- 【Spring Cloud】Feign接口调用
- Spring Cloud(五):服务消费者Feign
- 使用Spring Cloud Feign远程调用
- Spring Cloud之Feign调用token丢失
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用MYSQL实现Oracle的Start with...Connect By递归树查询
- 1186: 机器指令
- Spring Cloud 客服端负载均衡 Ribbon
- Kafka 设计与原理详解
- JavaScript学习笔记apply、call、bind用法说明
- Spring Cloud 声明式服务调用 Feign
- Spring Cloud 注册中心Eureka
- Python进阶
- Android 的Activity.getWindowManager().getDefaultDisplay().getWidth()过时了
- SSH原理记录
- PHP缓存 flush与ob_flush
- group_concat()函数总结
- DisplayTag工具类,转自谷歌论坛
- Nio简单介绍,本地操作,通道,缓冲区的简单使用,编码和解码