前言:一般情况下我们通常使用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)