目录
如果我们利用RestTemplate发起远程调用的代码时会存在一些问题比如:
•代码可读性差,编程体验不统一
•参数复杂URL难以维护
- String url="http://teacherservice/getTeacher";
- Teacher teacher = restTemplate.getForObject(url, Teacher.class);
OpenFeign是一个显示声明式的WebService客户端。使用OpenFeign能让编写Web Service客户端更加简单。使用时只需定义服务接口,然后在上面添加注解。OpenFeign也支持可拔插式的编码和解码器。spring cloud对feign进行了封装,使其支持MVC注解和HttpMessageConverts。和eureka(服务注册中心)和ribbon组合可以实现负载均衡。
在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求,非常的方便。
cloud官网介绍Feign:Spring Cloud OpenFeign
OpenFeign源码:GitHub - OpenFeign/feign: Feign makes writing java http clients easier
@FeignClient 实现的是声明式的、模块化的Http客户端,可以让我们对其他服务接口的访问更边界就像是controller和service之间的调用一样。
@FeignClient属性如下:
- @FeignClient(name="teacherservice")
- public interface TeacherServiceFeign {
- @GetMapping("/getTeacher/{id}")
- Teacher getInfo(@PathVariable("id") String id);
- }
在的启动类添加 @EnableFeignClients注解开启Feign的功能
用注解@EnableFeignClients启用feign客户端;扫描和注册feign客户端bean定义
@EnableFeignClients注解中的basePackges属性中是一个数组,可以填写多个值,其主要作用是指定当前模块中需要用到那些地址下的feign接口,起到一个discovery发现feign接口的作用。

俩个为俩个不同的端口的service端,客户端向8002端口的studentservice发送一个请求(/getInfo/{id})以后,8002端口的studentservice需要往teacherservice发送一个请求(/getTeacher/{id})返回数据。
统一管理版本信息
- <groupId>org.examplegroupId>
- <artifactId>eurek-testartifactId>
- <version>1.0-SNAPSHOTversion>
- <modules>
- <module>eurek-servemodule>
- <module>student-servicemodule>
- <module>teacher-servicemodule>
- modules>
-
-
- <packaging>pompackaging>
- <parent>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-parentartifactId>
- <version>2.3.12.RELEASEversion>
- <relativePath/>
- parent>
- <properties>
- <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
- <java.version>1.8java.version>
- <spring-cloud.version>Hoxton.SR10spring-cloud.version>
- <mysql.version>5.1.47mysql.version>
- <mybatis.version>2.1.1mybatis.version>
- properties>
- <dependencyManagement>
- <dependencies>
-
- <dependency>
- <groupId>org.springframework.cloudgroupId>
- <artifactId>spring-cloud-dependenciesartifactId>
- <version>${spring-cloud.version}version>
- <type>pomtype>
- <scope>importscope>
- dependency>
-
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-alibaba-dependenciesartifactId>
- <version>2.2.5.RELEASEversion>
- <type>pomtype>
- <scope>importscope>
- dependency>
- dependencies>
- dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- dependency>
- dependencies>
pom文件
- <dependencies>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
-
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
- dependency>
- dependencies>
启动类
- @SpringBootApplication
- public class TeacherApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(TeacherApplication.class,args);
-
- }
-
- }
yml配置文件
- server:
- port: 8002
- spring:
- application:
- name: teacherservice
- cloud:
- nacos:
- server-addr: localhost:8848
Teacher类
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public class Teacher implements Serializable {
- private String name;
- private String sex;
- }
TeachertController
- @RestController
- public class TeacherController {
-
-
- @GetMapping("/getTeacher/{id}")
- public Teacher getInfo(@PathVariable("id") String id){
- return new Teacher("张三-"+id,"男");
- }
- }
pom文件
- <dependencies>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
-
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
- dependency>
- <dependency>
- <groupId>org.springframework.cloudgroupId>
- <artifactId>spring-cloud-starter-openfeignartifactId>
- dependency>
- dependencies>
yml配置文件
- server:
- port: 8002
- spring:
- application:
- name: studentservice
- cloud:
- nacos:
- server-addr: localhost:8848
启动类
- @SpringBootApplication
- @EnableFeignClients
- public class StudentApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(StudentApplication.class,args);
-
- }
-
- }
Teacher类
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public class Teacher implements Serializable {
- private String name;
- private String sex;
- }
TeacherServiceFeign
- @FeignClient("teacherservice")
- public interface TeacherServiceFeign {
- @GetMapping("/getTeacher/{id}")
- Teacher getInfo(@PathVariable("id") String id);
- }
个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:
服务名称:teacherservice
请求方式:GET
请求路径:/getTeacher/{id}
请求参数:String id
返回值类型:Teacher
这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。
StudentController
- @RestController
- public class StudentController implements Serializable {
- @Autowired
- TeacherServiceFeign teacherServiceFeign;
-
- @GetMapping("/getInfo")
- public Teacher getInfo(){
- Teacher teacher = teacherServiceFeign.getInfo("111");
- return teacher;
- }
-
- }
GET http://localhost:8002/getInfo
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 17 Oct 2023 02:46:43 GMT
Keep-Alive: timeout=60
Connection: keep-alive{
"name": "张三-111",
"sex": "男"
}
Feign可以支持很多的自定义配置,如下表所示:
| 类型 | 作用 | 说明 |
|---|---|---|
| feign.Logger.Level | 修改日志级别 | 包含四种不同的级别:NONE、BASIC、HEADERS、FULL |
| feign.codec.Decoder | 响应结果的解析器 | http远程调用的结果做解析,例如解析json字符串为java对象 |
| feign.codec.Encoder | 请求参数编码 | 将请求参数编码,便于通过http请求发送 |
| feign. Contract | 支持的注解格式 | 默认是SpringMVC的注解 |
| feign. Retryer | 失败重试机制 | 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试 |
一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可。