SpringCloud-声明式Rest调用Feign
前言:一般情况下我们通常使用RestTemplate来实现声明式远程调用,但是当参数过多,那么效率就会变得很低,并且难以维护,所以在微服务当中也有声明式Rest调用的组件Feign
一、Feign简介
Feign是Netflix开发的声明式、模板化的http客户端,Feign可以帮我们更加便捷、优雅地调用HTTP API。在SpringCloud中使用Feign非常简单,创建一个接口,并在接口上加上注解,就完成了声明式调用;
二、Feign与SpringCloud的整合简单使用
注:本次学习记录是基于之前的Eureka介绍和Ribbon介绍之上实践,这里只展示关键代码,其余代码可在代码示例中查看;
1、创建基于Eureka和Ribbon的服务端和两个客户端生产者、消费者:
Server:
<?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>com.cn</groupId> <artifactId>eureka-ribbon-server</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.13.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- 添加spring-boot的maven插件 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
pom.xml
server.port=8761 #注意:这两个配置eureka默认为true,要改成false,否则会报错,connot connect server #表示是否将自己注册在EurekaServer上 eureka.client.register-with-eureka=false #表示是否从EurekaServer获取注册信息 eureka.client.fetch-registry=false eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
application.properties
package com.cn; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * @program: springcloud-example * @description: 启动类 * @author: * @create: 2018-06-15 15:43 **/ @SpringBootApplication @EnableEurekaServer public class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class,args); } }
ServerApplication.java
Client生产者:
<?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>com.cn</groupId> <artifactId>eureka-ribbon-client2</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.13.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- 添加spring-boot的maven插件 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
pom.xml
server.port=8763 spring.application.name=client-87 eureka.client.service-url.defaultZone=http://localhost:8761/eureka
application.properties
package com.cn; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * @program: springcloud-example * @description: * @author: * @create: 2018-06-15 16:05 **/ @SpringBootApplication @EnableDiscoveryClient public class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); } }
ClientApplication.java
package com.cn.contorller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * @program: springcloud-example * @description: * @author: * @create: 2018-06-15 16:12 **/ @Controller public class ClientController { @GetMapping("/getUser") @ResponseBody public String getUser() { System.out.println("获取用户成功"); return "{\"username\":\"张三\",\"age\":\"10\"}"; } }
ClientController.java
2、在消费者module中的maven依赖中添加相关依赖库,创建Feign访问接口,并注解,通过识别Eureka提供的应用名称,来找对应的请求路径:
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>
<groupId>com.cn</groupId>
<artifactId>eureka-feign-client</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</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-feign</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 添加spring-boot的maven插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties:
server.port=8762 spring.application.name=client-8762 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
Feign接口:
import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; @FeignClient(name = "CLIENT-87") public interface UserFeign { @RequestMapping("/getUser") public String getUser(); }
FeignController:
package com.cn.controller;
import com.cn.feign.UserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @program: springcloud-example
* @description:
* @author:
* @create: 2018-06-15 15:55
**/
@RestController
public class FeignController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@Autowired
private UserFeign userFeign;
@RequestMapping("/getUser")
public String getUser() {
return userFeign.getUser();
}
@GetMapping("/loadInstance")
public String loadInstance() {
ServiceInstance choose = this.loadBalancerClient.choose("client-87");
System.out.println(choose.getServiceId()+":"+choose.getHost()+":"+choose.getPort());
return choose.getServiceId() + ":" + choose.getHost() + ":" + choose.getPort();
}
}
在ClientApplication.java启动类中加入@EnableFeignClients注解:
package com.cn; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; /** * @program: springcloud-example * @description: * @author: * @create: 2018-06-15 15:51 **/ @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); } /** * @Description: * @Param: * @return: * @Author: * @Date: 2018/6/15 */ @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
3、分别启动Server、Client生产者、Client消费者,并调用访问http://localhost:8761、http://localhost:8762/getUser,如图:
调用成功!
参考书籍:《SpringCloud与Docker微服务架构实战》周力著
代码示例:https://gitee.com/lfalex/springcloud-example( eureka-feign-client、 eureka-ribbon-server、 eureka-ribbon-client2这三个module)