在本系列的 上一篇文章 中,演示如何使用 Hystrix 的熔断功能。在本文中,将演示如何使用 OpenFeign 简化 Rest 客户端的开发。
OpenFeign是spring cloud中服务消费端的调用库,通常与ribbon,hystrix等组合使用,简化了访问服务的代码和配置。
新建一个微服务项目
在 IDEA 中新建一个普通的 maven 项目,将其 groupId 命名为: cn.com.hohistar.tutorial, artifactId 命名为: springcloud-openfeign-client, 然后将项目的 pom.xml 替换为如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| <?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>
<groupId>cn.com.hohistar.tutorial</groupId> <artifactId>springcloud-openfeign-client</artifactId> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.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>Finchley.SR1</spring-cloud.version> </properties>
<dependencies>
<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>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
</project>
|
新建数据类
在 src/main/java 中新建一个名为: cn.com.hohistar.cloud.model 的包(package), 并在其中增加一个名为: Todo 的类, 代码如下:
1 2 3 4 5 6 7 8 9 10
| @Data public class Todo {
private Long id;
private String title;
private String desc;
}
|
因为所有的服务返回都别规范为 ApiResult 的格式,所以还需要加入 ApiResult 类的定义在 model 包中。 代码如下:
1 2 3 4 5 6 7 8 9 10 11
| @Data public class ApiResult<T> {
private Boolean succ;
private String code;
private String msg;
private T data; }
|
建立Feign实例
在 src/main/java 中新建一个名为: cn.com.hohistar.cloud.service 包(package),然后在包中新建一个接口,名为: TodoClient。其代码如下:
1 2 3 4 5 6 7
| @FeignClient(value = "cloud-todo-service") public interface TodoClient {
@RequestMapping(method = RequestMethod.GET, value = "/todo") ApiResult<List<Todo>> getTodos();
}
|
建立一个Rest API
在 src/main/java 中新建一个名为: cn.com.hohistar.cloud.api 包(package),然后在包中新建一个类,名为: FeignClientApi:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @RestController public class FeignClientApi {
@Autowired private TodoClient client;
@GetMapping("/f/todo") public ApiResult<List<Todo>> getTodos() {
return client.getTodos(); } }
|
建立应用启动类
在包 cn.com.hohistar.cloud 新建一个名为: FeignClientApplication 的类作为启动类, 代码如下:
1 2 3 4 5 6 7 8 9
| @SpringBootApplication @EnableEurekaClient @EnableFeignClients public class FeignClientApplication {
public static void main(String[] args) { SpringApplication.run(FeignClientApplication.class, args); } }
|
为应用加入配置信息
在 src/main/resource 中新建名为 application.yml 的配置文件,并加入以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| server: port: 9091
spring: application: name: cloud-feign-client
eureka: instance: leaseRenewalIntervalInSeconds: 1 leaseExpirationDurationInSeconds: 2 client: serviceUrl: defaultZone: http://localhost:8761/eureka/ healthcheck: enabled: true lease: duration: 5
|
运行程序检验结果
启动应用后,用浏览器访问:
1
| http://localhost:9091/f/todo
|
可以看到类似的结果:
1
| {"succ":true,"code":null,"msg":null,"data":[{"id":1,"title":"Call Metting","desc":""},{"id":2,"title":"Print File","desc":""},{"id":3,"title":"Call Metting","desc":""},{"id":4,"title":"Print File","desc":""}]}
|
加入熔断功能
在 pom.xml 文件中加入对 hystrix 的依赖库。
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
|
在 application.xml 中加入如下培训信息,允许熔断
1 2 3
| feign: hystrix: enabled: true
|
为了使用自定义的 fallback 方法,需要修改 TodoClient 接口,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @FeignClient(value = "cloud-todo-service", fallback = TodoClient.TodoClientFallback.class) public interface TodoClient {
@RequestMapping(method = RequestMethod.GET, value = "/todo") ApiResult<List<Todo>> getTodos();
@Component static class TodoClientFallback implements TodoClient {
@Override public ApiResult<List<Todo>> getTodos() {
ApiResult<List<Todo>> res = new ApiResult<>(); res.setSucc(false);
return res; } } }
|