SpringCloud中的OpenFeign调用解读
作者:一个风轻云淡
基本介绍
引进
如果我们利用RestTemplate发起远程调用的代码时会存在一些问题比如:
•代码可读性差,编程体验不统一
•参数复杂URL难以维护
String url="http://teacherservice/getTeacher"; Teacher teacher = restTemplate.getForObject(url, Teacher.class);
OpenFeign概述
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
OpenFeign作用
- OpenFeign的设计宗旨式简化Java Http客户端的开发。Feign在restTemplate的基础上做了进一步的封装,由其来帮助我们定义和实现依赖服务接口的定义。在OpenFeign的协助下,我们只需创建一个接口并使用注解的方式进行配置(类似于Dao接口上面的Mapper注解)即可完成对服务提供方的接口绑定,大大简化了Spring cloud Ribbon的开发,自动封装服务调用客户端的开发量。
- OpenFeign集成了Ribbon,利用ribbon维护了服务列表,并且通过ribbon实现了客户端的负载均衡。与ribbon不同的是,通过OpenFeign只需要定义服务绑定接口且以申明式的方法,优雅而简单的实现了服务调用。 @FeignClient
@FeignClient
实现的是声明式的、模块化的Http客户端,可以让我们对其他服务接口的访问更边界就像是controller和service之间的调用一样。
@FeignClient属性如下:
- name:指定该类的容器名称,类似于@Service(容器名称)
- url: url一般用于调试,可以手动指定@FeignClient调用的地址
- decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
- configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
- fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
- fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
- path: 定义当前FeignClient的统一前缀,当我们项目中配置了server.context-path,server.servlet-path时使用
@FeignClient(name="teacherservice") public interface TeacherServiceFeign { @GetMapping("/getTeacher/{id}") Teacher getInfo(@PathVariable("id") String id); }
@EnableFeignClients
在的启动类添加 @EnableFeignClients注解开启Feign的功能
用注解@EnableFeignClients启用feign客户端;扫描和注册feign客户端bean定义
@EnableFeignClients注解中的basePackges属性中是一个数组,可以填写多个值,其主要作用是指定当前模块中需要用到那些地址下的feign接口,起到一个discovery发现feign接口的作用。
Java代码实战
实战架构
俩个为俩个不同的端口的service端,客户端向8002端口的studentservice发送一个请求(/getInfo/{id})以后,8002端口的studentservice需要往teacherservice发送一个请求(/getTeacher/{id})返回数据。
父工程pom文件
统一管理版本信息
<groupId>org.example</groupId> <artifactId>eurek-test</artifactId> <version>1.0-SNAPSHOT</version> <modules> <module>eurek-serve</module> <module>student-service</module> <module>teacher-service</module> </modules> <packaging>pom</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR10</spring-cloud.version> <mysql.version>5.1.47</mysql.version> <mybatis.version>2.1.1</mybatis.version> </properties> <dependencyManagement> <dependencies> <!-- springCloud --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!--nacos的管理依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
teacher-service服务
pom文件
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- nacos客户端依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </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,"男"); } }
student-service服务
pom文件
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- nacos客户端依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </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即可。
到此这篇关于SpringCloud之OpenFeign调用解读的文章就介绍到这了,更多相关SpringCloud OpenFeign调用解读内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!