GitHub
- https://github.com/hjyang19/microservicecloud.git
- https://github.com/hjyang19/microservicecloud-config.git
Feign 服务接口调用
- 1-Feign 概述
- 1.1-是什么
- 1.2-能干嘛
- 2-Feign 使用
- 3-Feign 总结
1-Feign 概述
官网:https://github.com/OpenFeign/feign
1.1-是什么
官方解释:http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign
Feign 是一个声明式 Web Service 客户端。使用 Feign 能让编写 Web Service 客户端更加简单,它的使用方法是定义一个接口,然后在上面添加注解,同时也支持 JAX-RS 标准的注解。
Feign 也支持可拔插式的编码器和解码器。SpringCloud 对 Feign 进行了封装,使其支持了 SpringMVC 标准注解 和 HttpMessageConverters。
Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡。
Feign 是一个声明式的 Web 服务客户端,使得编写 Web 服务客户端变得非常容易,只需要创建一个接口,然后在上面添加注解即可。
1.2-能干嘛
Feign 旨在使编写 Java Http 客户端变得更容易。
前面在使用 Ribbon + RestTemplate 时,利用 RestTemplate 对 Http 请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以 Feign 在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。
在 Feign 的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是 Dao 接口上面标注 Mapper 注解,现在是一个微服务接口上面标注一个 Feign 注解即可),即可完成对服务提供方的接口绑定,简化了使用 SpringCloud Ribbon 时,自动封装服务调用客户端的开发量。
Feign 集成了 Ribbon:利用 Ribbon 维护了 MicroServiceCloud-Dept 的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与 Ribbon 不同的是通过 Feign 只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
2-Feign 使用
a、右击父工程 microservicecloud,新建子模块 microservicecloud-consumer-dept-feign
b、复制子模块 microservicecloud-provider-dept-80 中 pom.xml 到子模块 microservicecloud-consumer-dept-feignc、修改子模块 microservicecloud-consumer-dept-feign 中 pom.xml
<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>
<parent>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservicecloud-consumer-dept-feign</artifactId>
<dependencies>
<dependency><!-- 自己定义的api -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- Ribbon相关 -->
<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-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
</project>
d、修改子模块 microservicecloud-consumer-dept-feign,目录 /src/main/java 中新建包 com.atguigu.springcloud
e、复制子模块 microservicecloud-provider-dept-80 中包 com.atguigu.springcloud 内容到子模块 microservicecloud-consumer-dept-feign 包 com.atguigu.springcloud
f、修改子模块 microservicecloud-consumer-dept-feign,包 com.atguigu.springcloud 启动类重命名为 DeptConsumer80_Feign_App.java
删除报错 Ribbon 自定义算法配置。
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer80_Feign_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_Feign_App.class, args);
}
}
g、修改子模块 microservicecloud-consumer-dept-feign,包 com.atguigu.springcloud.controller 中 DeptController_Consumer.java 重命名为 DeptController_Feign.java
h、复制子模块 microservicecloud-provider-dept-80 中目录 /main/resources 内容到子模块 microservicecloud-consumer-dept-feign 目录 /main/resources
i、修改子模块 microservicecloud-api 中 pom.xml
<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>
<!-- 子类里显示声明才能有继承表现,无意外就是父类的默认版本,否则自己定义 -->
<parent>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservicecloud-api</artifactId>
<!-- 当前 Module 所需 jar 包,按需求添加,若父类已包含可不写版本号 -->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
</project>
j、修改子模块 microservicecloud-api,目录 /src/main/java 中新建包 com.atguigu.springcloud.service
k、修改子模块 microservicecloud-api,包 com.atguigu.springcloud.service 中新建接口 DeptClientService.java
package com.atguigu.springcloud.service;
import com.atguigu.springcloud.entities.Dept;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
@FeignClient(value = "MICROSERVICECLOUD-DEPT")
public interface DeptClientService {
@RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
public Dept get(@PathVariable("id") long id);
@RequestMapping(value = "/dept/list", method = RequestMethod.GET)
public List<Dept> list();
@RequestMapping(value = "/dept/add", method = RequestMethod.POST)
public boolean add(Dept dept);
}
l、子模块 microservicecloud-api,执行 Maven 命令 mvn clean install
m、修改子模块 microservicecloud-consumer-dept-feign,包 com.atguigu.springcloud.controller 中 DeptController_Feign.java添加子模块 microservicecloud-api 中接口 DeptClientService.java
package com.atguigu.springcloud.controller;
import com.atguigu.springcloud.entities.Dept;
import com.atguigu.springcloud.service.DeptClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DeptController_Feign {
@Autowired
private DeptClientService service = null;
@RequestMapping(value = "/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return this.service.get(id);
}
@RequestMapping(value = "/consumer/dept/list")
public List<Dept> list() {
return this.service.list();
}
@RequestMapping(value = "/consumer/dept/add")
public Object add(Dept dept) {
return this.service.add(dept);
}
}
n、修改子模块 microservicecloud-consumer-dept-feign,包 com.atguigu.springcloud 中启动类 DeptConsumer80_Feign_App.java
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.atguigu.springcloud"})
@ComponentScan("com.atguigu.springcloud")
public class DeptConsumer80_Feign_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_Feign_App.class, args);
}
}
o、测试 Feign 使用
- 启动 Eureka 集群(子模块 microservicecloud-eureka-7001、microservicecloud-eureka-7002、microservicecloud-eureka-7003)
- 启动微服务集群(子模块 microservicecloud-provider-dept-8001、microservicecloud-provider-dept-8002、microservicecloud-provider-dept-8003)
- 启动子模块 microservicecloud-consumer-dept-feign
- http://localhost/consumer/dept/get/1Feign 自带负载均衡配置项。
3-Feign 总结
Feign 通过接口的方法调用 Rest 服务(之前是 Ribbon + RestTemplate),该请求发送给 Eureka 服务器(http://MICROSERVICECLOUD-DEPT/dept/get/1),通过 Feign 直接找到服务接口,由于在进行服务调用的时候融合了 Ribbon 技术,所以也支持负载均衡作用。