1. 定义
Feign是Netflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS-2.0以及WebSocket。Feign 可帮助我们更加便捷、优雅地调用HTTP API。 在Spring Cloud中,使用Feign非常简单——只需创建接口,并在接口上添加注解即可。 Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。Spring Cloud对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Eureka,从而使得Feign的使用更加方便。
2. 同Ribbon对比
Ribbon还是采用暴露url的方式调用服务,而Feign可以使用如下方法调用。
productCenterFeignApi.getString()
其中productCenterFeignApi就是Feign客户端。
3. 示例
3.1 简单使用
父工程参考这篇文章里的父工程Nacos使用
3.1.1 新建子工程feign-api
pom文件:
<?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">
<parent>
<artifactId>Learn</artifactId>
<groupId>zyz.springCloudAlibaba</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>feign-api</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
接口类:
package com.zyz.feignapi;
import com.zyz.comfig.ProductCenterFeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(name = "product-center")
public interface ProductCenterFeignApi {
@RequestMapping("/getString")
String getString();
}
3.1.2 新建子工程feign-order
pom文件:
<?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">
<parent>
<artifactId>Learn</artifactId>
<groupId>zyz.springCloudAlibaba</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>feign-order</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--加入nocas-client-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>zyz.springCloudAlibaba</groupId>
<artifactId>feign-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Controller类:
package com.zyz.controller;
import com.zyz.feignapi.ProductCenterFeignApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private ProductCenterFeignApi productCenterFeignApi;
@RequestMapping("/get")
public String get(){
return productCenterFeignApi.getString();
}
}
启动类:
package com.zyz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignOrderApplication {
public static void main(String[] args) {
SpringApplication.run(FeignOrderApplication.class,args);
}
}
配置文件为:
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: order-center
server:
port: 8801
3.1.3 新建子工程feign-product
pom文件为:
<?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">
<parent>
<artifactId>Learn</artifactId>
<groupId>zyz.springCloudAlibaba</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>feign-product</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--加入nocas-client-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>zyz.springCloudAlibaba</groupId>
<artifactId>feign-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Controller类:
package com.zyz.controller;
import com.zyz.feignapi.ProductCenterFeignApi;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController implements ProductCenterFeignApi {
@Override
@RequestMapping("/getString")
public String getString() {
System.out.println("调用我啦");
return "Hello";
}
}
启动类:
package com.zyz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class FeignProductApplication {
public static void main(String[] args) {
SpringApplication.run(FeignProductApplication.class,args);
}
}
配置文件:
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: product-center
server:
port: 8804
分别启动feign-product和feign-order项目,并访问feign-order里的接口,可以成功看到输出。
3.2 加入日志
默认情况下,Feign调用在客户端是没有日志的,这里把日志功能添加进去。
这里修改feign-api和feign-order这两个项目。
3.2.1 修改feign-api项目
新增配置类ProductCenterFeignConfig
package com.zyz.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
public class ProductCenterFeignConfig {
@Bean
public Logger.Level level() {
return Logger.Level.BASIC;
}
}
修改ProductCenterFeignApi接口
package com.zyz.feignapi;
import com.zyz.config.ProductCenterFeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(name = "product-center", configuration = ProductCenterFeignConfig.class)
public interface ProductCenterFeignApi {
@RequestMapping("/getString")
String getString();
}
3.2.3 修改feign-order项目
修改配置文件
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: order-center
server:
port: 8801
#开启日志
logging:
level:
com:
zyz:
feignapi: debug
3.3 与Ribbon配合使用,加入负载均衡逻辑
由于Feign底层支持Ribbon,所以这里只需要在配置文件中添加配置即可。
修改feign-order的配置文件
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: order-center
server:
port: 8801
#负载均衡配置
product-center:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
#开启ribbon饥饿加载,解决微服务调用第一次很慢的情况下
ribbon:
eager-load:
enabled: true
#可以指定多个微服务用逗号分隔
clients: product-center
#开启日志
logging:
level:
com:
zyz:
feignapi: debug
大功告成,可以自行测试一下。