1. Feign 简介
Feign 是声明性(注解)Web 服务客户端。它使编写 Web 服务客户端更加容易。要使用 Feign,请创建一个接口并对其进行注解。它具有可插入注解支持,包括 Feign 注解和 JAX-RS 注解。Feign 还支持可插拔编码器和解码器。Spring Cloud 添加了对 Spring MVC 注解的支持,并支持使用 HttpMessageConverters,Spring Web 中默认使用的注解。Spring Cloud 集成了 Ribbon 和 Eureka 以及 Spring Cloud LoadBalancer,以在使用 Feign 时提供负载平衡的 http 客户端。
Feign 是一个远程调用的组件 (接口,注解) http 调用的,Feign 集成了 ribbon ,ribbon 里面集成了 eureka
2. Feign 快速入门

实现步骤:
- 导入依赖feign的starter
- 启动引导类加@EnableFeignClients注解
- 编写FeignClient接口,使用SpringMVC的注解
- 在Controller中注入Feign接口,直接调用,无需实现类
- 访问接口测试
实现过程:
1. 导入依赖feign的starter (导入到消费者中)
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2. 编写服务提供者provider-order-service
-
修改服务提供者配置文件
server: port: 8081 spring: application: name: provider-order-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka instance: instance-id: ${spring.application.name}:${server.port} prefer-ip-address: true -
修改启动类
@SpringCloudApplication @EnableFeignClients//开启Feign功能 开启当前服务的feign客户端支持,feign底层封装了一个请求的客户端(RestTemplate【httpclient,okhttp,..】 public class ProviderApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class,args); } } -
增加一个访问接口
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class OrderController { /** * 订单服务下单接口 * @return */ @GetMapping("doOrder") public String doOrder() { System.out.println("有用户来下单了"); return "下单成功"; } }
3. 编写服务消费者consumer-user-service
-
修改服务消费者配置文件
server: port: 8081 spring: application: name: consumer-user-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka instance: instance-id: ${spring.application.name}:${server.port} prefer-ip-address: true -
创建远程调用的Feign接口
package com.lihw.feign; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; /** * @FeignClient 声明是 feign 的调用 * value = "provider-order-service" value 后面的值必须和提供者的服 务名一致 */ @FeignClient(value = "provider-order-service") public interface UserOrderFeign { /** * 描述: 下单的方法 这里的路径必须和提供者的路径一致 * @return java.lang.String */ @GetMapping("doOrder") String doOrder(); } -
创建Controller
import com.bjpowernode.feign.UserOrderFeign; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Autowired private UserOrderFeign userOrderFeign; /** * 用户远程调用下单的接口 * @return */ @GetMapping("userDoOrder") public String userDoOrder() { String result = userOrderFeign.doOrder(); System.out.println(result); return result; } } -
修改consumer-user-service启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableEurekaClient @EnableFeignClients //标记 feign 的客户端 public class ConsumerUserServiceApplication { public static void main(String[] args) { SpringApplication.run(ConsumerUserServiceApplication.class, args); } }
4. 测试
访问:http://localhost:8081/userDoOrder
consumer-user-service ---> /userDoOrder ---> 通过 feign 调用 /doOrder ---> provider-order-service 下单成功
3. Feign 调用参数处理
3.1 传参问题
Feign 传参确保消费者和提供者的参数列表一致 包括返回值 方法签名要一致
- 通过 URL 传参数,GET 请求,参数列表使用@PathVariable(“”)
- 如果是 GET 请求,每个基本参数必须加@RequestParam(“”)
- 如果是 POST 请求,而且是对象集合等参数,必须加@Requestbody 或者@RequestParam
3.2 时间日期参数问题
使用 feign 远程调用时,传递 Date 类型,接收方的时间会相差 14 个小时,是因为时区造成的
处理方案:
- 使用字符串传递参数,接收方转换成时间类型(推荐使用)不要单独传递时间
- 使用 JDK8 的 LocalDate(日期) 或 LocalDateTime(日期和时间,接收方只有秒,没有毫秒)
- 自定义转换方法
传参总结:
get 请求只用来传递基本参数 而且加注解@RequestParam
post 请求用来传递对象参数 并且加注解@RequestBody
4. Feign日志功能
日志级别:
-
NONE 默认的,不显示日志
-
BASE 仅记录请求方法,URL ,响应状态码及执行时间
-
HEADERS 在 BASE 之上增加了请求和响应头的信息
-
FULL 在 HEADERS 之上增加了请求和响应的正文及无数据
创建配置类:
package com.bjpowernode.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLogger() {
return Logger.Level.FULL;
}
}
修改配置文件
logging:
level:
com.bjpowernode.feign.UserOrderFeign: debug